Year #3, Week #15 đ» đ
Homework Plan
- 1 day Monkey Assignment #23 đ
- 1 day review all flashcards in your (new Netlify) app.
- 1 day touch typing practice
- 2 days Flashcards API assignment (Login/Signup)
- 3 days Execute Program homework
Flashcards API Homework (Login/Signup)
- đ Read through the whole assignment first before beginning.
- Read the ânode password hashingâ section of âNew Stuffâ from last week.
- Make a new branch.
- In your main
src/index.ts
file, add a line under where you add the CORS middleware that says:app.use(express.json())
â this will allow express to parse JSON bodies sent to your routes. - Next, make a shell route handler in index.ts that listens for
POST
requests to/signup
with this code in it:
app.post(`/signup`, async (req, res) => {
console.log(`json body received:`, req.body);
res.json({ temp: true });
});
- Next add a âsign upâ request in your
api.http
file, with this content:
###
# Signup
POST http://localhost:YOUR_PORT_HERE/signup HTTP/1.1
Content-Type: application/json
{
"email": "foo@bar.com",
"password": "cafed00d"
}
###
Be sure to change
YOUR_PORT_HERE
to be your port.Start your dev server, send the new request â you should see the JSON body logged out in your terminal, and it should return the json
{"temp": true}
.Take a brief tour of your
route-responders.ts
and database/mock database files to remind yourself how they work. Remember, the idea behind the concept of a route responder is to extract a testable function out from the messy world of HTTP requests and side effects. And the reason we have a database abstraction is so that we can mock various responses for the sake of testing. Weâre going to be adding two new route responders and two new methods on our database abstraction to implement login/signup, so make sure youâre clear and fresh on how this works.Next, youâll actually implement the signup feature, now that youâve got the shell of a route roughed in, and the JSON body getting parsed. It should meet these criteria (read them all ahead of time):
- The work should not be done right inside the function in index.ts â rather,
the
req.body
should be passed as an input to a new route responder which returns a status and some json, so it is testable. - The route responder should be fully tested, including all of the error states, like invalid json, user already exists, database borks unexpectedly, etc.
- Youâll need to create three new methods on your
Database
abstraction type:createUser
,createUserToken
, andgetUserByEmail
. Unlike thegetAllCards
method, all three of these will end up having one or more arguments as input. - When the route is invoked, check if there is a user with that email address already in the database, if so, the route should error with status code 400 and some appropriate error message.
- If a user does not exist with that email address, create a new user in the
users
table with the given email address and password. - Donât insert the plain text password, insert the hashed version instead
(refer to new stuff above, youâll need to install
bcrypt
as a dependency and@types/bycrypt
as a dev dependency) - Once the user row is created, also create a new row in
user_tokens
. It should have the foreign key set up correctly (ie, theuser_id
row should be set to the new usersid
value). - The json you return when things go well should be:
{"token":"SOME_UUID"}
where SOME_UUID is the id of theuser_tokens
row you created. This is what will eventually be used to authenticate the user, and will be stored in a cookie in the web app. - your jest tests should all be passing, and then (if you havenât done so
before), put the route-responder into the
/signup
function in index.ts and hook it up. Test that it works by starting your dev server and sending the request fromapi.http
. (Note, if you send the request twice, the second one should fail because the email address would be a duplicate, unless you change the email address. Verify this.) - because this is a pretty involved feature to implement, and youâve only once worked with route responders and your database abstraction, Iâve made monkey style videos for you to use. I would like you to try to work on your own somewhat, and only use the videos until the idea clicks for you, then try to keep working on your own, same as with monkey. Try to avoid just watching the videos and copying what I do, try to internalize the concepts and use the video to keep you on the right track.
- videos for this section are: video 1 and video 2.
- The work should not be done right inside the function in index.ts â rather,
the
when youâve got all that working, review your code, clean things up, and commit. (NOTE: this is a logical stopping point, to break this up into 2 days)
Next, create another route following basically the same steps, but this time for json POST-ed to
/login
. Differences/requirements (read all ahead of time):- the posted json body should be in exactly the same format
- I want you to also have a test request in
api.http
- when the route is hit, instead of creating a user, it should try to select an existing user from the database with that email address.
- if the email address is not found, send a 404 with an error message.
- if the user is found in the db, compare the plain text password sent in the JSON body with the hash stored in the database (see ânew stuffâ for an example of how to do this). If the passwords donât match, return 400 with an error message.
- if the passwords do match, create a new token, much like you did for the other feature, and send back the same response.
- as with the other one, this should be encapsulated in a route responder, and the database access should be done behind a method on the db abstraction.
- the route responder should be thoroughly tested, with cases covering not finding the user, passwords not matching, generic database problems, and the happy (successful) path.
- video for this section
when youâve got it all working, review your code, clean things up, and commit.
Push up a MR, review your diffs, clean stuff up, and slack me the URL.
Monkey #23 đ
- Address all feedback from prior MRâs, and merge.
- Create a new branch.
- Double-check that you did the first two steps.
- Start where you left of last time, after the 3.6 Conditionals section, which is labeled 3.7 Return Statements. Complete the section.
- Commit your work.
- As always, make sure to try to do as much as you can without the videos, but always also watch the videos and update your code to (mostly) match.
- Video link
- Submit a MR, Review your diffs and fixup!!, then slack the MR url