All language subtitles for 014 Password Reset Functionality_ Setting New Password_Downloadly.ir_en

af Afrikaans
ak Akan
sq Albanian
am Amharic
hy Armenian
az Azerbaijani
eu Basque
be Belarusian
bem Bemba
bn Bengali
bh Bihari
bs Bosnian
br Breton
bg Bulgarian
km Cambodian
ca Catalan
ceb Cebuano
chr Cherokee
ny Chichewa
zh-CN Chinese (Simplified)
zh-TW Chinese (Traditional)
co Corsican
hr Croatian
cs Czech
da Danish
nl Dutch
en English
eo Esperanto
et Estonian
ee Ewe
fo Faroese
tl Filipino
fi Finnish
fr French
fy Frisian
gaa Ga
gl Galician
ka Georgian
de German
el Greek
gn Guarani
gu Gujarati
ht Haitian Creole
ha Hausa
haw Hawaiian
iw Hebrew
hi Hindi
hmn Hmong
hu Hungarian
is Icelandic
ig Igbo
id Indonesian
ia Interlingua
ga Irish
it Italian
ja Japanese
jw Javanese
kn Kannada
kk Kazakh
rw Kinyarwanda
rn Kirundi
kg Kongo
ko Korean
kri Krio (Sierra Leone)
ku Kurdish
ckb Kurdish (Soranรฎ)
ky Kyrgyz
lo Laothian
la Latin
lv Latvian
ln Lingala
lt Lithuanian
loz Lozi
lg Luganda
ach Luo
lb Luxembourgish
mk Macedonian
mg Malagasy
ms Malay
ml Malayalam
mt Maltese
mi Maori
mr Marathi
mfe Mauritian Creole
mo Moldavian
mn Mongolian
my Myanmar (Burmese)
sr-ME Montenegrin
ne Nepali
pcm Nigerian Pidgin
nso Northern Sotho
no Norwegian
nn Norwegian (Nynorsk)
oc Occitan
or Oriya
om Oromo
ps Pashto
pl Polish
pt-BR Portuguese (Brazil)
pt Portuguese (Portugal)
pa Punjabi
qu Quechua
ro Romanian
rm Romansh
nyn Runyakitara
ru Russian
sm Samoan
gd Scots Gaelic
sr Serbian
sh Serbo-Croatian
st Sesotho
tn Setswana
crs Seychellois Creole
sn Shona
sd Sindhi
si Sinhalese
sk Slovak
sl Slovenian
so Somali
es Spanish
es-419 Spanish (Latin American)
su Sundanese
sw Swahili
sv Swedish
tg Tajik
ta Tamil
tt Tatar
te Telugu
th Thai
ti Tigrinya
to Tonga
lua Tshiluba
tum Tumbuka
tr Turkish
tk Turkmen
tw Twi
ug Uighur
uk Ukrainian
ur Urdu
uz Uzbek
vi Vietnamese
cy Welsh
wo Wolof
xh Xhosa
yi Yiddish
yo Yoruba
zu Zulu

Original subtitles

And now let's finally create the last part

of the Password Reset Functionality,

where we actually set the new password for the user.

And so, just like before, let's start by defining the steps

that we're gonna take for this resetPassword flow.

So, first off, get user based on the token.

Then as the second step, we will set the new password

but only if token has not expired,

and there is a user.

So in that case, set the new password.

Then after that, we need to update

the changedPasswordAt property

for the current user,

and then finally, as is usual in this functionality,

is to log the user in.

Basically, send the JSON Web Token to the client.

Okay, so a lot of work to do, and so let's get started.

And so, remember from the last video, that the reset token

that is actually sent in the URL

is this non-encrypted token here.

So, actually this one.

But the one that we have in the database

is the encrypted one.

So we talked about that before, and so what we now

need to do, is to basically encrypt

the original token again,

so we can then compare it with the one that is stored,

so the encrypted one in the database.

So, we actually did something similar before

with the password, but with the password,

we couldn't compare it as easily as we can with this one,

again because for the password

we used the quite complex bcrypt algorithm,

which in this case, we didn't.

So, here it's very straightforward.

All we need to do again, is to encrypt the token

and compare it with the encrypted one in the database.

So, let's say hashedToken, and so we will actually now

need the crypto package here as well.

Const crypto and then require('crypto').

Now right.

Then let's go back, and so,

we use crypto.createHash.

Remember, then the name of the algorithm again, sha256,

then .update, basically for the place, for the string

that we want to hash.

And so, that one is, remember in req.params.

So we then use this one for a long time .token.

And so again, it is a parameter,

because we specified so here in the URL, so like this.

So, it's now a parameter called token.

And so, of course, here it's req.params.token.

And then, finally, we also need to say digest

and convert it to hexadecimal.

Now this is basically the same

as we had before, where we encrypted the original one,

and so we could refactor this into its own function,

but let's just keep it simple here.

So, now let's actually get the user based on this token.

Because that is actually, the only thing

that we know about the user right now.

We have no email, we have nothing, so this token

is the only thing that can identify the user.

And so we can now, basically, query the database

for this token.

And it will then find the user which has this token.

So, await, as we already know, and then User.findOne.

So, that property is called passwordResetToken

and we are looking for the hashedToken.

And now of course, we need to declare it as async

and prep it into catchAsync.

Give it a save, that should fix this bug,

and indeed it does.

So, this will find user who has the token

that will send via URL.

But, right now, we're not taking

the token expiration date into consideration.

And so how could we do that?

Well, basically, what we want is to check

if the passwordResetExpires property

is greater than right now.

Because if the expires date is greater than now,

it means it's in the future, which in turn means,

that it hasn't yet expired.

And so, that's a very easy way

in which we can actually do this right with this query.

So, passwordResetExpires,

which is where that date is stored,

and now all we need to check

if it is actually greater than right now.

And so we know how to do that already with MongoDB, right?

So, new object and then the greater operator

and then what we want to compare it with is Date.now,

and this will actually be a timestamp of right now,

but behind the scenes, MongoDB will then convert everything

to the same, and therefore be able

to compare them accurately.

And so with this we can, at the same time,

find the user for the token and also check if the token

has not yet expired.

So, great.

So, next up we want to, of course, send an error

if there is no user, or basically, if the token has expired.

But that's, in this case, the same,

because if the token has expired, well then it will simply

not return any user.

And so all we need to do is to say, if no user,

well then, as always, return next, that's not mext.

So new AppError, and let's say

Token is invalid or has expired.

And then 400, so bad request.

And so then, if there is no error,

and if next is not called,

well then let's actually set the password.

So, we already got the user and now it's very simple:

user.password is equal to req.body.password.

And that's because we will of course, send the password

and also passwordConfirm via the body.

So let's duplicate that

and passwordConfirm as well.

And then also, let's basically delete the reset token

and the expired.

So passwordResetToken, so just like we did before,

we set it to undefined, and now user.password expires

equals to undefined.

All right.

And again, of course, we now need to save it,

because this only modifies the document,

it doesn't really update.

So it doesn't really save it.

So, await user.save.

And in this case, we actually don't have to turn off

the validators, because indeed we want to validate.

For example, we want the validator to confirm

if the password is equal to passwordConfirm.

And so that validator automatically

does all that work for us.

Then the third step, what we're gonna do actually

in the end, and so what we're gonna do next

is to basically lock the user in.

So in other words, send the JSON Web Token.

And let's get that code from here, so this one.

And again, we're already doing this here

in three different places.

So here in the login, also in signup,

and now for the third time, down here.

And so, sometime in the future, we will refactor that

into its own function.

But for now, we're good like this.

And so, let's actually now go ahead and test this.

So this reset token that we had before

has already expired, and so we need to ask

for a new one, basically.

So let's come to Postman and hit our forget password route.

Let's just reduce the clutter here

and get rid of all of these open tabs

that we no longer need.

Actually here we're gonna need this test

for this Reset Password,

because remember, that this one actually gets back

a JSON Web Token, and so we want to save that

into the environment variable,

just like we did with all the others.

So I'm doing that now, just so that I don't forget it.

All right, anyway, let's start with, basically,

forgetting the password.

So sending that request out, which again,

takes some times because of sending the email,

but here we go, and let's now go to our email,

and so that just arrived a few seconds ago.

So, it is this, of course, this token.

So let's grab it, copy it and now back to Postman,

we use it in the Reset Password, as the URL.

Okay, make sense?

So again, we're sending that token right in the URL.

Then here, let's specify the body,

because now, we need to actually specify our new password.

So password and let's say newpass.

And then...

And here let's call it something else,

because for now, I actually want to see an error.

And of course, this is called passwordConfirm.

So let's see what happens when we try to do this.

Let's wait for it, and we get password is shorter

than the minimum allowed length.

Okay, so let's change that, 123, and here let's say 1234.

So I want them to be different.

But you see that the validation here worked just fine,

even when updating the password with save.

So, and now we get Passwords are not the same!

So again, that's a validation error.

And remember, actually, that this is the whole reason

why we need to use save and not update.

So before, for updating tours,

we used to use findOneAndUpdate, but now,

for everything related to passwords and to the user,

we always use save, because we always want to run

all the validators, and above all,

the save middleware functions.

So, for example, the ones where the passwords are encrypted.

So let's end it now.

Oh, I didn't actually correct it, sorry for that.

And but now it should actually work.

And indeed, we get success, and we get a new token.

So great, let's see if this token is actually valid.

So if we can, get all the tours using this brand new token.

And here we go.

So, our new token actually works, and now for this user,

so for hello@jonas, these two properties

should actually be gone.

So the password expires and the token should be gone,

since, well, since that's what we did in our code.

And so, yeah, they are no longer here.

Now all we need to do actually, is this missing step here,

which is to update the passwordAt property

for this current user.

But that shouldn't be all too hard,

and so let's quickly go back to the userModel,

which is where we are gonna do that using middleware.

And let's actually put all the middleware

together here at the top.

So, userSchema.pre and again dot save,

and then a function with next.

Again, this function here is gonna run

right before a new document is actually saved.

And so, it's the perfect place

for actually specifying this property.

And I could, of course, have done it in a controller

right next to here to this code, for example.

But I really want this to happen, kind of, automatically.

So, kind of behind the scenes.

Because later on, we will have another place

where we update the password and then we would make sure

that we're including the same code there.

And like this, again, it happens,

kind of, behind the scenes,

without us having to worry about it at all.

Now, when exactly do we actually want to set the

passwordChangedAt property to right now?

Well we only want it when we actually modified

the password property.

And I'm not sure if we used this trick before,

but anyway, let's use it now.

So if we have not modified, so if not this.isModified,

so just like this,

and then the name of the property, so password.

So in that case, return right away

and run the next middleware.

Okay, not like this, but like this.

So again, if we didn't modify the password property,

well then of course,

do not manipulate the passwordChangedAt.

But what about creating new document?

Well, when we create a new document,

then we did actually modify the password,

and then we would set the passwordChangedAt property, right?

Well, in the current implementation we actually would.

But there is something else that we can use here.

So, basically, we want to exit this middleware function

right away, if the password has not been modified

or if the document is new, and so we can use

the isNew property.

And again, this is one of these very nice things

that are learned by reading your documentation.

And so, I cannot stress enough how important it is

to really read the documentations when you need something

that you cannot find anywhere.

Because, there really is so much stuff in there

that is completely impossible to teach in one course.

Anyway, if the code passes this verification here,

well, then let's very simply say,

this.passwordChangedAt = Date.now.

And then, we call next.

Now, in theory, this should work just fine,

but actually, in practice,

sometimes a small problem happens.

And that problem is that sometimes saving to the database

is a bit slower than issuing the JSON Web Token,

making it so that the changed password timestamp

is sometimes set a bit after

the JSON Web Token has been created.

And so that will then make it so that the user

will not be able to log in using the new token.

Because, remember, the whole reason this timestamp here

actually exists, is so that we can compare it

with the timestamp on the JSON Web Token, right?

So, just to remember,

it is, well, so right here, where we check if the user

has changed the password after the token was issued.

And so, down here, where we then created this new token

in reset password.

So right here, remember, we create this new token,

and so again, sometimes it happens that this token

is created a bit before the changed password timestamp

has actually been created.

And so, we just need to fix that by subtracting one second.

So, basically, a thousand milliseconds.

And so that then will put the passwordChangedAt one second

in the past, okay, which will then of course,

not be 100% accurate, but that's not a problem at all,

because one second here doesn't make any difference at all.

It's a small hack, but again, it's no problem.

So putting this passwordChanged one second in the past,

will then ensure that the token is always created

after the password has been changed.

So, this works now, but as always,

let's also quickly test it.

Okay, so back to Postman.

Let's do a new Reset Password,

or actually, that's not what I wanted at all,

but it's a great thing to see

that the code is actually working.

So, The token is invalid or has expired,

and that's because, well, 10 minutes have passed

since I actually created that token.

And I think we hadn't yet tested this,

and so it's great that it now accidentally, actually did it.

So again, this comes, in case you're wondering

what the hell happened,

so that's of course this error message here.

And so it means, that it didn't find any user

which has this token or which has a token that is

more than 10 minutes in the past.

And so, indeed what I wanted to do, is forget password.

So, let's wait for it.

So 8.6 seconds,

but that might be because of my internet connection.

So if you run this on a server,

it's probably gonna be a lot faster.

So let's grab that here, back to Postman, and now

we reset the password, again with this password,

doesn't really matter if it's the same as the old one.

And, so now we have our success here.

And now back to Compass.

Let's reload, and indeed, we get the passwordChangedAt.

And so that is actually right now.

And so, if we now tried to actually use this token,

for example, to access this protected route,

well then that should work because of that small,

one second tag that we did.

So, it did and so just like this, we actually now finished

our Password Reset Functionality.

So that was quite a bit of code, but of course,

it's totally worth it.

So, you should always offer this functionality

in your web application, because otherwise,

a user that forgets his password is completely screwed,

they can non longer use your application,

and so, that's of course a terrible practice.

Anyway, this kind of finishes, already,

the authentication and authorization part of this section.

So again, it's quite complete

and I had a lot of fun implementing this.

So, this part for me is where web applications

really start coming to life.

I know that it's not really visible at this point,

with all these, just tokens and copying tokens

and paste them somewhere else.

That's not the usual idea that we have of logging in,

I know, but of course again, a bit later,

when we finally start building the dynamic website,

then we will of course,

keep using this authentication that we just built

and then it will also become visual on that dynamic website.

Next up, we will implement functionality for updating

the user and also deleting it,

and after that, we will then also talk about security.

So that's what's ahead for the rest of the section,

so make sure not to miss that.

Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.