Instructor: We've now got some fantastic logic
for creating a new user account.
We read in the email and password of request,
we see if there's already a duplicate.
If there's not, we go ahead and create a user and save it.
So this is all looking pretty great right now.
One thing that you may have noticed if you've played around
with the current logic at all in Postman
is that while we can successfully create an email,
create a user with an email and a password,
I just submitted these and I got success is true.
If I delete the email, I don't send any email along,
let's see what happens.
I'm gonna send and I still get success true back
even though I didn't provide an email address.
Let's open up Robomongo and see
what this looks like inside the database.
So I'm gonna open Robomongo.
I'm gonna open my connections tab
and I'm gonna connect to localhost.
At this point, you should now see an auth database in here.
If we expand that and then we expand collections,
we can see this users collection
and it's called "users", lowercase U specifically,
specifically 'cause that's how we wired up
to Mongoose inside of our user model file.
Over here, you can see that I've got two records.
One has the email that I just created
and then the other one has a password and ID
but not an email address.
So it looks like our server is currently
letting us save or create new users,
even if an email and password were not passed in.
So let's add a little check just to guard against that case.
Inside of my authentication controller,
I'm gonna say, "If there is not an email
(keyboard keys clattering)
or there is not a password,
(keyboard keys clattering)
return early with a status of 422,
and send back a message of,
'You must provide email and password',
like so."
Now, if I go back over to Robomongo
and I delete both of the records that I just made,
so I'm just gonna forcibly delete them
by right clicking and then clicking "Delete document."
Now I'll go back over to Postman.
I'm going to make my request again without a password,
excuse me, again without an email.
I'll send, and now I correctly get an error message
that says, "You must provide an email and a password."
And if I go look at Robomongo,
I did not create any users.
So I successfully exited out early and said,
"Nope, don't need to make a record in this case
because the email and password are not valid."
I could also put in a little bit of authentication
or a little bit more validation here,
just to verify that the email that was passed in
is actually looks like an email.
You know, it has an "@" symbol,
a domain on it, et cetera, et cetera.
So this is looking pretty good.
I like how we are.
I like where we're at.
We're handling a couple edge cases here.
Just one small thing.
If I create a new user in Postman,
so I'm gonna go back over to Postman,
I'm going to add on email here,
(keyboard keys clattering)
and then, I'll send it across.
The account was successfully made.
I'm gonna go back over to Robomongo.
I'm gonna refresh by hitting command R.
Now I can see that
I successfully have an email and a password.
Just one small thing here.
The password is send in my database as plain text.
So in the security world, this is a big, tremendous no-no,
we never wanna save a plain text password.
If some malicious actor ever got access to our database,
they could grab all of our users' credentials,
not only the emails, but also the unencrypted passwords.
And this is basically a worst case scenario.
If your users' passwords and plain text
get out there in the open,
you're gonna have a very hard time
explaining that to your customers.
So whenever we store a password,
we always want to store a encrypted password,
an encrypted version.
So we need to go back to our,
into our logic and update the logic
that's gonna save the password here.
And we wanna replace this with an encrypted password.
To handle this, we're going to use a library called Bcrypt.
Bcrypt is a extremely popular library
for encrypting passwords before they get saved.
Bcrypt is a separate package in Node,
so it's something that we have to install ourselves.
As with all other packages that we've had ever installed,
we are going to install it from the NPM tool.
So back over my terminal,
I'm going to end my server process.
And then I'll run "npm install
-: -save Bcrypt-nodejs".
This is gonna grab the node version of Bcrypt
and install it.
(clearing throat)
So Bcrypt is very compact, very small,
and so it installs almost immediately.
And then we'll go ahead and,
start our server back up with "npm run dev".
Okay.
So one thing about Bcrypt, you know, it's fantastic library,
it really gives us a lot of security.
The only kind of weird thing about it is that
it is not the easiest thing to understand from the Gitgo.
So here's what we're gonna do.
We're going to wire up Bcrypt,
we're gonna implement it inside our app,
we're gonna see it work,
and then we're gonna talk about exactly what's going on
with Bcrypt, okay?
So we're gonna do a lot of typing to start off with.
We're gonna put on the code.
It's gonna look pretty weird, but after we do that,
we'll talk about exactly what's going on.
So here's the code we're gonna write.
We're gonna flip over to our user model,
so our user.js file.
At the top, we're going to import the Bcrypt library.
So const
Bcrypt require
Bcrypt nodejs.
And then, here's where things are gonna get
a little interesting.
So just again, bear with me for a little bit.
I'm gonna add another section in here that says,
"On Save Hook,
(keyboard keys clattering)
encrypt password".
So now we're gonna do the typing.
This is gonna be the, kind of crazy part.
Again, just bear with me for a bit.
We're going to take our userSchema object,
which we defined above.
We're going to call "pre" on it,
P R E.
We're gonna pass a string of save
and then a function with an argument.
Next,
again, we're gonna talk about all this stuff.
Just let's get the code on the screen first
because it's a lot easier to explain
after it's on the screen.
I'm gonna put const user equals this,
then, Bcrypt
genSalt
number 10.
We're gonna put in another function
whose arguments are "err" and "salt".
We'll say, "if err
return next err."
So again, this is a little bit of error handling.
Then just one more big step in here.
We're gonna say, "Bcrypt hash
user.password,
salt,
null",
another function
with arguments, "err" and "hash".
Finally, if err
return next err,
otherwise,
user.password equals hash,
and next.
All right, so a lot of typing.
I would love if you pause the video at this point
and just took a look at all the code on here.
Make sure that you transcribed everything correctly
'cause we just did a whole bunch of typing
without really being clear about what was going on.
I also encourage you to open up your terminal
and just verify that you're not getting any typos
or any errors in here.
If you're getting any typos or any errors at this point,
you might have a typo in the code that you just wrote.
So, do make sure that everything is showing up correctly.
All right, so we've got the code on the screen.
Let's go through an explanation
of exactly what's going on,
in the next section.