Welcome back.
We have our final end point.
Sign in where we're finally able to sign in users.
Now there might be something that you have realized when we were working on register.
That is we're inserting the user with email, name and joined, but we're never updating our login table.
If I do select star from login, well we have nothing there.
That's not good is it.
We want to create something every time a new user logs in and actually capture their passwords or the
hash of their passwords.
So let's work on that in this video. In order for us to do this.
We first need to register a user and grab their passwords.
Now for us to do this we need to insert into another database.
But first let's use bcrypt to hash out a password that we get.
If you remember we already have bcrypt installed and it's from a previous video we can go back to the
bcrypt Node.js package and although I've shown you the asynchronous way of doing things we're going to
do the synchronous one because it's simpler.
Just keep in mind that with synchronous it means that as this is working javascript is not going to
get executed on the next line versus with asynchronous if you run bcrypt hash,
Javascript keeps executing.
And then when this returns it will come back here.
This way is just a little bit cleaner for now.
So we'll use this code example.
We will copy this, go to our register, and in here - we don't want to compare yet.
We just want to store, so we can say const hash we want to bcrypt the password.
So let's change this to password.
And now that we have the password hash we need to make sure that we update the users as well as the
login table so that we don't have an issue
like this where we have these users.
But if we go to the logon Well we have absolutely nothing.
So to avoid this we have an important concept of transactions and transactions are these code blocks
that we can add to make sure that when we're doing multiple operations on a database if one fails then
they all fail.
If for some reason, I can't enter something in the users table, but I can in login, as long as it's wrapped
around a transaction they both fail so that I never have these inconsistencies.
Let me show you how to do that.
With the users table I want to have this part. I'm going to indent it a little bit.
And before we do the users, I want to create a transaction. I'm going to say DB dot transaction and now
we have a transaction in KNEX and if we go to the KNEX they have transactions and you can read
about them here and SQL has transaction as well.
If we go back this transaction gets a trx parameter that we can now use instead set of the DB to make
sure that whatever we do is a transaction. The first transaction we want to do is that we want to insert
into the users or into the login the hash in the email, so we can say hash email or hash hash that we
just received from bcrypt, and then email which we just got from request dot body.
Instead of just doing this syntax which we can do as well.
We can do into
login and then finally returning the email of the user.
Now that we have this returned we can say dot then email because we're returning the email.
And just to keep it separate from the request or body we'll say that this is the login email and this
long email will now be used in here. So we can just copy and paste this
into here.
Just make sure the spacing is right. And we can use the log in email after we've updated the log and
table to update the login email so we don't really change anything.
The only thing we did was this block we moved it inside a dot then so that we first update the login
table we get the login email and in order to make sure that these are both part of the transaction
instead of doing DB here we have the TRX object.
So we will do TRX and let's save and see what happens.
And then I go back to our example here, our NodeMon.
We have a register with John.
If I click send.
All right I get ID 11 John, I get e-mail if I go into the logon.
I don't have login here.
If I go into users I don't have John either.
So something must have gone wrong.
The last thing we want to do is at the end, and you can read about this in the KNEX section, we can do-
dot then
TRX commit, because we weren't able to send these because we didn't say that if all these pass then
commit send this transaction through.
And if I do dot catch, I'll do
TRX roll back
So now let's give this a go.
I'm going to click send, I get a response. If I go to users.
I have John and if I go to login I have John with the hash.
The only thing that's wrong here is that I have this syntax for the e-mail, which is not what we want.
That's a simple fix because we're giving the login email here.
Remember we're returning an array.
So if I go like this let's do John 1 send
go to our example of login.
That looks good.
And login our users we have John1 at gmail dot com.
Amazing.
So this transaction is probably the trickiest part to get used to.
And you can see here it is a little bit.
But once you get the syntax it becomes very easy.
You create a transaction when you have to do more than two things at once, and you use this TRX object
instead of the DB now, to do these operations.
In my case I insert it into login, it returned the email, and then we use the login e-mail to also return
another TRX transaction to insert into the users and responded with Json and then in order for this
to get added We have to make sure that we commit and then in case anything fails we roll back the changes.
If I enter the same user again I get unable to register. If I send the wrong information I'll get unable
to register. Perfect.
Now that we have this working we can finally go to our signin. we are containing the hash now on to
our table and all we need to do now is, well let's remove this.
And in this signin we can do a DB we'll do a select, we'll select email and hash from login.
Dot then we'll get the e-mail and hash.
So let's get response or in this case let's just do data
and let's just console log to see what we receive
I'm going to save go to signin and see if we still have something. There you go. Let's do signin body
John cookies I senD this. I'm not responding with anything so it hangs.
But if I go back I see that I get e-mail and hash and I receive everything because well I haven't selected
any specific criteria.
We can say that now we want to do the WHERE clause where email
equals the request
dot body dot email. If that's the case let's save and try again, send.
We got a syntax error because we don't need an object here.
There you go.
Let's try that again.
Click send.
This will hang so we'll cancel.
And there you go.
We have John's e-mail and hash.
And now we need to check to see if John put in the right password.
So within data here we can grab the array which is the first one.
And now use bcrypt. And remember with bcrypt we have compare sync.
We can simply say bcrypt dot compare sync with whatever the user entered.
In this case request a body dot password with the hash, in our case we can just say data zero dot
hash.
If this returns true well let's just have a const is valid.
In that case - let's make this a little bit smaller so you can see
we'll say if is valid
this will return true or false.
We'll do a response dot Json with the user information.
So we'll have to do a DB dot select star from
users dot where
email equals to request dot body dot email then we'll get the user.
And finally within here we can
move this to response dot Json user array first item.
And if there's some issue getting that down we'll say catch
error response dot
Json we'll do status again 400 Json unable to get user, and also down here because we're still doing
the database search right here.
And this doesn't need to be a transaction because, well we're just checking, we're not modifying any of
the database items in here. We can say dot catch
if there's an error.
We can just respond dot status 400 This time we can say wrong credentials.
All right let's give that a go.
I'm going to save no errors here.
Fine go back to postman and click.
John cookies send.
I get it 200.
OK but I didn't receive a user so let's console log here.
And this is a simple error.
We always want to make sure that we're returning this so that this database knows about it.
We always want to make sure we're returning.
Let's try that again.
I'm going to send with the right information with password cookies.
All right I got 200.
But let's do a console log here.
Is valid. We'll save and see what we get here.
We're going to send OK.
Is valid is running and then users is zero.
So we're not grabbing the users properly.
Let's see why.
And that is because our e-mail for John.
Remember we made a mistake of not returning it properly.
So let's register a new user and make sure that they have the right password.
We'll go back to register we'll register with Eddy password it will be hello and his name will be Andy
We'll click send. Perfect.
And now if we sign in with Eddy
you don't need to send the name just the password.
If we click send.
All right we've got 200.
Looks like it's working.
But if Eddy enters the wrong password.
All right.
This is still hanging.
Because we never stated if this is false what should happen.
In our case we want to say response dot status 400 dot Json wrong credentials and make sure
that I do an else statement here.
And put that up here.
Let's save
Click send. Wrong credentials.
But if I click hello
I get Eddy.
That is awesome.
We have our entire signin flow working.
We can remove the console logs here
and now that we have everything working we have our users our new Eddy user and he's also part of the login
with the hash with storing everything securely because in our database we never store Eddy's password.
And we finally have our logs working. In the next video we're finally going to test all this out with
our Front-End and hopefully everything works well and looks like we don't need this database any more.
Good job everybody.
I'll see you on the next one.
Bye-bye.