Year #3, Week #14 đ» đ„
New stuff we learned this week: đ€
Hashing passwords in Node
import bcrypt from "bcrypt";
// hash a password
const plainTextPassword = `cafed00d`;
const hash = await bcrypt.hash(plainTextPassword, 10);
// then, store the `hash` var (NOT the plain text password)
// in your database
// check a password against the stored hash
// NEVER storing the plain text
const isMatch = await bcrypt.compare(
// this would be a password you get POST-ed to you
someSubmittedPassword,
// this is the hash you retrieved from the database
hashFromDb
);
Some useful SQL Goodies
- When creating a table, you can add the phrase
IF NOT EXISTS
right afterCREATE TABLE
. If the table already exists, the command will be skipped. This makes it safe and error free to run aCREATE TABLE
query operation multiple times. - the MySQL
TIMESTAMP
data type holds a combination of date and time, in UTC, and is automatically converted to/from your timezone by mysql. - The format of a
TIMESTAMP
isYYYY-MM-DD HH:MM:SS
, like1970-01-01 00:00:01
. - When creating a table, you can specify that the default value of a TIMESTAMP column should be the âcurrent timestampâ, like this:
CREATE TABLE cats (
name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
- You can also specify a column to always be updated to the current timestamp by
specifying
ON UPDATE CURRENT_TIMESTAMP
whenever any value in the row is updated. This is really useful and very frequently leveraged for a column calledupdated_at
, like this:
CREATE TABLE cats (
name TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
- You can have your database enforce that all values in a column MUST be UNIQUE by adding a âUnique constraintâ. When creating a table, hereâs the syntax:
CREATE TABLE students (
id TEXT NOT NULL,
name VARCHAR(255) NOT NULL,
slack_username VARCHAR(255) NOT NULL,
UNIQUE (slack_username)
);
Semver
Homework Plan
- 1 day Monkey Assignment #22 đ
- 1 day review all flashcards in your (new Netlify) app.
- 1 day touch typing practice
- 1 day Flashcards API assignment (Migrations)
- 1 day CS50 Pset 3 C Assignment (Plurality, Runoff)
- 3 days Execute Program homework
CS50 Pset 3 (Plurality, Runoff)
- First, make sure youâve addressed any feedback and merged MRâs from previous work on your CS50 repo.
- Make a new branch.
- Very carefully read the whole description of the
plurality
 problem here - Starting with this code,
complete the implementation of
plurality.c
. (Hint: make sure you carefully refer to the âSpecificationâ section of the assignment when working on filling out the functions, it gives very detailed instructions on what each function should do). - Make sure to test your code, including edge cases, to prove that it works.
- Commit your work.
- Next, very slowly and carefully reach the whole description of the
runoff
 problem here - Starting with this code,
complete the implementation of
runoff.c
.- Hint 1: again, make sure you refer to the âSpecificationâ section of the problem as you work through each function, since it gives helpful detailed requirements, and hints for each one.
- Hint 2: you might want to end up debugging this code, if it doesnât work
the way you think. If you donât have vscode debug files setup, refer to the
new stuff where I explained that. Youâll need to make use of the
"args"
property in thelaunch.json
to pass in command line arguments, like"args": ["Bob", "Alice", "Charlie"]
. - Hint 3: Pay special attention to trying to understand the
preferences
multi-dimensional array, itâs a bit of a head-scratcher. The first index is the index of the voter. The second dimension is the rank. And theint
stored in the array represents the index of the candidate voted for. So, if the first voter ranked the second of three candidates in third place,preferences[0][2]
would equal1
, because0
is the index of the voter (first),2
is the rank (third place), producing1
which is the second index, aka, the second candidate.
Flashcards API Homework (Migrations)
- Slowly and carefully read the SQL portion of âNew Stuffâ above ^^^.
- Make sure youâve addressed any prior feedback and merged your last MR from your last chunk of work in the Flashcards API repo.
- make a new branch.
- Go back a few weeks in the âNew Stuffâ, find the section about doing mysql âdumpsâ. Dump your production database and keep it somewhere safe, just in case you mess something up with this homework.
- Next, double-check that your Api project will be talking to your âdevâ
database, NOT your production database. Check your
.env
file, and any logic where you pass the database name to theSimpleSQL
constructor. - Next, spend a little bit of time studying the README for htc simple migrations.
- Install the library, setup the db provider as instructed, and create your
first migration in a file called
./src/migrations/01_CreateCategoriesTable.ts
. You should start by copy/pasting the example for a migration in the readme, and then delete the innerds of theup
anddown
function. That way youâll be sure you are implementing theMigration
interface correctly. - Update the code that you copy/pasted in the last step so that the migration
will be responsible for creating (and dropping) the
categories
table. Since you already have this table, you can get most of the SQL from SQL Pro, like I showed you in class. Be sure to add aIF NOT EXISTS
clause (see new stuff above). Thedown
method should remove the table. - Before you test it, add a
console.log()
inside yourup
method, and then run the migration by typingnpx simple-migrate up:all
. You should get no errors and see what you logged out in yourup
method. If you have errors, read them and try to figure out what you did wrong. The migration library is very picky about where your files are and what they are named. - Once you get your migration to run successfully, open up SequelPro and refresh
the tables. You should see a new table added by the migration library called
__htc_simple_migrations
. This table keep track of which migrations have already been run. It should have one row already, indicating the migration it just ran. - Try running the same
mpx simple-migrate up:all
command again⊠It should say that itâs skipping the migration because it was already executed. - Just for your learning sake, letâs force the migration to re-run by manually
deleting the row from the
__htc_simple_migrations
table (do this in SequelPro). This causes the tool to forget that the migration had been run. Run the migration again â it should be safe to do because you added theIF NOT EXISTS
in the previous step. The migration library should report that the migration was run, and you should see the console.log again. - Make sure your SQL code is formatted nicely, with newlines, etc, and then
remove the
console.log
, and commit your work. - Make another migration for creating (and dropping) your
cards
table. - Commit your work.
- Next, weâre going to add a
users
table. It should have 5 columns:id
(should be VARCHAR(36) and the primary key)email_address
(VARCHAR(128), and must be UNIQUE)password
(TEXT)created_at
(TIMESTAMP and must be set automatically)updated_at
(TIMESTAMP and must be set automatically, and update automatically)
- experiment with the SQL to create this table in SequelPro until you get it
right, then copy it into your migration. Make sure to make a
down()
that removes the table. - When you think youâve got it, test the migration by running
npx simple-migrate up:one
, then see what you got in SequelPro. It should have created the table for you. - Since you donât have any data at all in that table yet, test your migrations
âdownâ method by running
npx simple-migrate down:one
. Verify in SequelPro that the table was deleted. - Commit your work.
- Next, weâre going to add a
user_tokens
table, it should have 3 columns:id
(should be VARCHAR(36) and the primary key)user_id
(should be VARCHAR(36) and be a foreign key reference tousers.id
) (Hint: you might need to go back and review some previous new stuffs and/or homework where we learned about the syntax for Foreign Keys, or search on the mysql docs site))created_at
(TIMESTAMP and must be set automatically)
- Again, experiment with crafting the SQL query in SequelPro first, and then put it into your migration. Test the up and down, like you did with previous steps.
- Commit your work.
- Finally, make some npm scripts to simplify running your migrations. You can name them how you want, but you should have one at least for running all of your migrations up, and maybe one for reversing one migration.
- Commit your work.
- Submit a MR, review all your diffs, clean stuff up, and slack me the MR URL.
Monkey #22 đ
- 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 Infix Expressions section, which is labeled 3.6 Conditionals
- Complete the entire section, stopping at 3.7 Return statements.
- 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