Would you like to inspect the original subtitles? These are the user uploaded subtitles that are being translated:
1
00:00:00,960 --> 00:00:03,130
So, over the last few videos,
2
00:00:03,130 --> 00:00:06,220
we allowed a user to reset his password
3
00:00:06,220 --> 00:00:08,070
and then create a new one,
4
00:00:08,070 --> 00:00:09,910
but now we also want to allow
5
00:00:09,910 --> 00:00:13,383
a logged-in user to simply update his password
6
00:00:13,383 --> 00:00:15,740
without having to forget it,
7
00:00:15,740 --> 00:00:18,880
and so without that whole reset process.
8
00:00:18,880 --> 00:00:20,833
So, let's build that now.
9
00:00:22,620 --> 00:00:23,810
And, just like before,
10
00:00:23,810 --> 00:00:26,413
let's do that in our authentication controller.
11
00:00:28,420 --> 00:00:30,523
So, export.updatePassword.
12
00:00:35,142 --> 00:00:38,940
All right, and so, just like always,
13
00:00:38,940 --> 00:00:43,940
our three Middleware parameters here, and okay.
14
00:00:44,380 --> 00:00:48,250
Now remember that this password updating functionality is
15
00:00:48,250 --> 00:00:50,260
only for logged-in users,
16
00:00:50,260 --> 00:00:54,290
but still we need the user to pass in his current password,
17
00:00:54,290 --> 00:00:55,920
so in order to confirm
18
00:00:55,920 --> 00:00:58,990
that user actually is who he says he is.
19
00:00:58,990 --> 00:01:01,260
So, just as a security measure
20
00:01:01,260 --> 00:01:04,950
because imagine that someone would find your computer open
21
00:01:04,950 --> 00:01:08,150
and then be able to change passwords on the sites
22
00:01:08,150 --> 00:01:09,530
that you have currently open
23
00:01:09,530 --> 00:01:12,610
without being prompted for a password again.
24
00:01:12,610 --> 00:01:15,300
And so that would basically log you out
25
00:01:15,300 --> 00:01:18,260
of all your existing applications,
26
00:01:18,260 --> 00:01:21,000
which would, of course, be a terrible experience.
27
00:01:21,000 --> 00:01:23,800
And so, as a security measure, we always need to ask
28
00:01:23,800 --> 00:01:27,800
for the current password before updating it, all right.
29
00:01:27,800 --> 00:01:30,530
And, with that in mind, let's lay out all the steps
30
00:01:30,530 --> 00:01:32,760
that we need to take in order to implement
31
00:01:32,760 --> 00:01:36,030
this functionality just like before.
32
00:01:36,030 --> 00:01:39,530
So, first up, we need to get the user
33
00:01:39,530 --> 00:01:41,903
from the collection, basically.
34
00:01:44,840 --> 00:01:47,480
Then second, we need to check
35
00:01:47,480 --> 00:01:50,263
if the posted password is correct.
36
00:01:56,430 --> 00:01:57,880
Right.
37
00:01:57,880 --> 00:02:01,800
Then, third, so if the password is correct,
38
00:02:01,800 --> 00:02:04,623
then update the password.
39
00:02:07,170 --> 00:02:11,013
And finally, we need to again log the user in,
40
00:02:12,180 --> 00:02:16,610
so basically to send the jsonwebtoken back to the user,
41
00:02:16,610 --> 00:02:20,860
now logged in with the new password that was just updated.
42
00:02:20,860 --> 00:02:23,860
Okay, and this is actually all very similar to
43
00:02:23,860 --> 00:02:25,510
what we did already before,
44
00:02:25,510 --> 00:02:27,370
and so I'm leaving this one for you
45
00:02:27,370 --> 00:02:29,430
as a challenge, okay?
46
00:02:29,430 --> 00:02:32,660
So, please try to go ahead and implement this on your own,
47
00:02:32,660 --> 00:02:35,313
and if you need, you can of course take a look at the code
48
00:02:35,313 --> 00:02:36,800
that we wrote before,
49
00:02:36,800 --> 00:02:39,440
but really try to write the code on your own
50
00:02:39,440 --> 00:02:41,720
without copying too much, okay?
51
00:02:41,720 --> 00:02:44,140
So, you can take a look at the rest of the code to see
52
00:02:44,140 --> 00:02:47,680
how it works, but then don't really just copy it, okay?
53
00:02:47,680 --> 00:02:50,610
Because then you're not really gonna learn, all right.
54
00:02:50,610 --> 00:02:52,900
So, pause the video here, and I'll see you in a second
55
00:02:52,900 --> 00:02:54,083
with my solution.
56
00:02:57,510 --> 00:03:00,450
Okay, so I hoped you managed to implement this
57
00:03:00,450 --> 00:03:03,533
and to get it working, this is how I did it.
58
00:03:04,960 --> 00:03:08,963
So, as always, we create a new user variable,
59
00:03:09,970 --> 00:03:14,353
and in there we await the result of doing User.findById,
60
00:03:17,930 --> 00:03:20,940
and now where is this ID actually coming from?
61
00:03:20,940 --> 00:03:24,590
Well, remember again that this update password is only
62
00:03:24,590 --> 00:03:27,710
for authenticated, so for logged in users,
63
00:03:27,710 --> 00:03:30,830
and so therefore, at this point, we will already have
64
00:03:30,830 --> 00:03:33,123
the current user on our request object.
65
00:03:34,380 --> 00:03:37,273
Okay, so that's coming from the protect Middleware.
66
00:03:38,640 --> 00:03:42,670
So, req.user.id, and then remember
67
00:03:42,670 --> 00:03:46,933
that we need to explicitly ask for the password, okay?
68
00:03:48,830 --> 00:03:53,260
Because it is, by default, not included in the output.
69
00:03:53,260 --> 00:03:55,883
So, we defined that on the schema, remember?
70
00:03:56,860 --> 00:03:58,730
And, we actually need that password
71
00:03:58,730 --> 00:04:01,860
because now we want to compare it with the one
72
00:04:01,860 --> 00:04:03,690
that's stored in the database,
73
00:04:03,690 --> 00:04:05,300
and for that, just like before,
74
00:04:05,300 --> 00:04:08,850
we're gonna use this instance object
75
00:04:08,850 --> 00:04:10,720
that we have somewhere here.
76
00:04:10,720 --> 00:04:13,360
Yeah, so correctPassword, which is available
77
00:04:13,360 --> 00:04:15,250
on all the user documents,
78
00:04:15,250 --> 00:04:17,680
so it takes in the candidate password first,
79
00:04:17,680 --> 00:04:21,850
and then the actual user password, all right.
80
00:04:21,850 --> 00:04:23,370
Oh, and now it's giving me this error
81
00:04:23,370 --> 00:04:26,120
because, of course, I didn't declare this
82
00:04:26,120 --> 00:04:28,203
as an async function just yet.
83
00:04:29,610 --> 00:04:32,534
So, async, and before we forget it,
84
00:04:32,534 --> 00:04:36,577
let's wrap it into the catchAsync function here as well.
85
00:04:38,589 --> 00:04:40,513
Anyway, just like before,
86
00:04:40,513 --> 00:04:43,157
we basically want to create an error here
87
00:04:43,157 --> 00:04:46,402
if the current password is not correct,
88
00:04:46,402 --> 00:04:48,572
and so, let's write that in code.
89
00:04:48,572 --> 00:04:51,239
So, if not user.correctPassword,
90
00:04:53,870 --> 00:04:56,283
and then the candidate password remember,
91
00:04:56,283 --> 00:04:58,808
and so that one is gonna be in a body,
92
00:04:58,808 --> 00:05:03,808
in a property that we're gonna call the passwordConfirm.
93
00:05:03,980 --> 00:05:07,941
Okay, and then as a second argument the actual password,
94
00:05:07,941 --> 00:05:10,108
so that's a user.password.
95
00:05:11,036 --> 00:05:13,820
And then, remember that this is an asynchronous function,
96
00:05:13,820 --> 00:05:16,323
and so we need to also await it here.
97
00:05:18,400 --> 00:05:22,173
Good, so in case that the password is not correct,
98
00:05:24,020 --> 00:05:27,500
just like always, we create a new error here.
99
00:05:27,500 --> 00:05:32,000
So, new AppError, and this time we're saying
100
00:05:32,930 --> 00:05:37,930
your current password is wrong,
101
00:05:38,720 --> 00:05:43,660
and then status code 401 for unauthorized.
102
00:05:43,660 --> 00:05:45,650
All right, great.
103
00:05:45,650 --> 00:05:48,240
Now, if we make it to this point in code,
104
00:05:48,240 --> 00:05:51,750
so basically if the password is also correct,
105
00:05:51,750 --> 00:05:54,460
well then we can actually update the password,
106
00:05:54,460 --> 00:05:56,400
and how do we do that?
107
00:05:56,400 --> 00:05:58,763
Well, very simple, we did that before.
108
00:05:59,630 --> 00:06:04,630
All we say is user.password is equal to req.body.password,
109
00:06:08,200 --> 00:06:11,793
and then the same, of course, for the password confirm.
110
00:06:14,010 --> 00:06:17,560
Okay, and the validation will be done automatically
111
00:06:17,560 --> 00:06:21,300
by the validator that we specified on the schema,
112
00:06:21,300 --> 00:06:23,823
and that will be done once we actually save it.
113
00:06:24,690 --> 00:06:29,280
So, we await user.save,
114
00:06:29,280 --> 00:06:32,400
and so this time we do not turn off the validation
115
00:06:32,400 --> 00:06:35,920
because, of course, we want the validation to happen,
116
00:06:35,920 --> 00:06:39,120
so just as I said before, we want to check
117
00:06:39,120 --> 00:06:42,010
that the password confirm is actually the same
118
00:06:42,010 --> 00:06:44,560
as the password, right?
119
00:06:44,560 --> 00:06:45,570
Good.
120
00:06:45,570 --> 00:06:49,460
And, now just to really make sure that you understand
121
00:06:49,460 --> 00:06:53,533
why we didn't do something like user.findByIdAndUpdate.
122
00:06:56,530 --> 00:06:59,260
So, why didn't we do it like this?
123
00:06:59,260 --> 00:07:02,450
And, I know that I talked about this many times before,
124
00:07:02,450 --> 00:07:05,330
but I want you to understand one hundred percent
125
00:07:05,330 --> 00:07:07,990
why we cannot use this update,
126
00:07:07,990 --> 00:07:09,540
and it is for two reasons,
127
00:07:09,540 --> 00:07:12,143
so let me go back again to our model.
128
00:07:13,090 --> 00:07:14,650
So, the first one is
129
00:07:14,650 --> 00:07:18,920
that this validation here is not going to work, okay?
130
00:07:18,920 --> 00:07:22,670
And that's basically because this.password is not defined
131
00:07:22,670 --> 00:07:27,420
when we update, so when we use find by ID and update,
132
00:07:27,420 --> 00:07:29,440
because internally, behind the scenes,
133
00:07:29,440 --> 00:07:33,200
Mongoose does not really keep the current object in memory,
134
00:07:33,200 --> 00:07:36,230
and so therefore, this here is not going to work.
135
00:07:36,230 --> 00:07:39,130
And, as I said, I already talked about that before,
136
00:07:39,130 --> 00:07:42,650
so it's actually written out here as well, okay?
137
00:07:42,650 --> 00:07:45,600
But, it's really important to keep in mind not to use update
138
00:07:45,600 --> 00:07:49,340
for anything related to passwords, all right?
139
00:07:49,340 --> 00:07:51,160
So, this one is not going to work,
140
00:07:51,160 --> 00:07:53,640
and also, these two pre-saved
141
00:07:53,640 --> 00:07:56,510
Middlewares are also not going to work.
142
00:07:56,510 --> 00:07:59,820
So, if we used simply update for updating the password,
143
00:07:59,820 --> 00:08:03,000
then that password would not be encrypted,
144
00:08:03,000 --> 00:08:04,750
which is this first Middleware,
145
00:08:04,750 --> 00:08:07,530
and then also, the passwordChangedAt
146
00:08:07,530 --> 00:08:11,030
timestamp would also not be set, okay?
147
00:08:11,030 --> 00:08:12,830
So, none of this would work,
148
00:08:12,830 --> 00:08:15,943
and so again, we really need to do it like this.
149
00:08:17,470 --> 00:08:19,020
Let's just put that here again.
150
00:08:21,330 --> 00:08:24,430
And so now, (mumbles), we logged the user in,
151
00:08:24,430 --> 00:08:27,840
and sent the token back to the client.
152
00:08:27,840 --> 00:08:30,210
Now, that would actually be the fourth time
153
00:08:30,210 --> 00:08:32,320
that we did the same code,
154
00:08:32,320 --> 00:08:34,190
so basically this piece of code,
155
00:08:34,190 --> 00:08:36,710
and so, that's now very quickly refactor this
156
00:08:36,710 --> 00:08:38,409
into its own function.
157
00:08:38,409 --> 00:08:42,409
Now, this code actually is not the same everywhere.
158
00:08:42,409 --> 00:08:45,090
So, here we sent the status code 400,
159
00:08:45,090 --> 00:08:47,250
and we do not send the user,
160
00:08:47,250 --> 00:08:51,280
but then up here in the signup handler,
161
00:08:51,280 --> 00:08:53,680
we actually have a different status code,
162
00:08:53,680 --> 00:08:56,900
and we also sent the user to the client, okay?
163
00:08:56,900 --> 00:08:59,873
And so, let's make our function actually keep that in mind.
164
00:09:00,890 --> 00:09:05,890
So, let's create a function here,
165
00:09:06,140 --> 00:09:09,293
create and send token,
166
00:09:11,100 --> 00:09:14,350
and then the arguments that we need in here are the user
167
00:09:14,350 --> 00:09:17,070
because that's where the ID is stored.
168
00:09:17,070 --> 00:09:18,893
Then, we also want the status code,
169
00:09:20,220 --> 00:09:24,060
and of course, we need to have access to the response object
170
00:09:24,060 --> 00:09:26,940
in order to actually be able to send a response
171
00:09:26,940 --> 00:09:29,510
back to the client, okay?
172
00:09:29,510 --> 00:09:32,473
And so, basically now what we need is this code.
173
00:09:33,775 --> 00:09:35,930
So, let's copy it, put it here,
174
00:09:35,930 --> 00:09:38,700
and then replace irrelevant variables.
175
00:09:38,700 --> 00:09:42,480
So, the user is simply called user,
176
00:09:42,480 --> 00:09:44,963
so just like this, and here, the same.
177
00:09:46,470 --> 00:09:47,510
So, not new user,
178
00:09:47,510 --> 00:09:51,150
and then here we replace that with the status code,
179
00:09:51,150 --> 00:09:54,440
so the one that's coming in into our function,
180
00:09:54,440 --> 00:09:57,053
and so I guess that's actually it.
181
00:09:58,330 --> 00:10:01,070
So, let's now go ahead and replace it,
182
00:10:01,070 --> 00:10:06,070
so createSendToken, and here the user is called the newUser,
183
00:10:09,040 --> 00:10:10,763
the status code is 201,
184
00:10:12,260 --> 00:10:15,093
and then of course the response object.
185
00:10:16,730 --> 00:10:19,223
Okay, now we can get rid of this code,
186
00:10:20,680 --> 00:10:21,863
and let's just copy it.
187
00:10:23,200 --> 00:10:26,903
All right, so in the log in we of course also sent a token,
188
00:10:28,860 --> 00:10:32,630
but this time the user is actually called user
189
00:10:32,630 --> 00:10:34,243
and the status code is 200.
190
00:10:38,470 --> 00:10:39,920
And now, let's copy this one.
191
00:10:42,210 --> 00:10:45,853
So, the next one should be here, and reset password,
192
00:10:46,930 --> 00:10:48,400
and here it's actually the same,
193
00:10:48,400 --> 00:10:51,323
so the name is user and code 200,
194
00:10:53,740 --> 00:10:57,550
and now, finally, here it's also the same.
195
00:10:57,550 --> 00:11:02,360
And so, that finishes our update password function.
196
00:11:02,360 --> 00:11:03,740
Now, to make this work,
197
00:11:03,740 --> 00:11:06,830
we of course need to implement the route here as well
198
00:11:06,830 --> 00:11:08,033
in our user router.
199
00:11:09,900 --> 00:11:14,400
So, router.patch, and we will do a patch
200
00:11:14,400 --> 00:11:17,610
because we're actually changing, so we're manipulating
201
00:11:17,610 --> 00:11:21,460
the user document, and so that's what patch is for.
202
00:11:21,460 --> 00:11:24,590
And the route is called updateMyPassword.
203
00:11:29,060 --> 00:11:30,630
So, my password because it's
204
00:11:30,630 --> 00:11:34,420
for the currently logged in user, and then remember, again,
205
00:11:34,420 --> 00:11:36,810
this only works for logged in users,
206
00:11:36,810 --> 00:11:41,770
and so we need to use authController.protect,
207
00:11:41,770 --> 00:11:44,240
which will then also put the user object
208
00:11:44,240 --> 00:11:47,270
on a request object, okay?
209
00:11:47,270 --> 00:11:51,593
So, protect, and then authController update password
210
00:11:51,593 --> 00:11:55,640
that we just created, all right.
211
00:11:55,640 --> 00:11:59,593
And so, let's now actually go ahead and test this, okay?
212
00:12:02,720 --> 00:12:05,763
So, let's copy this route here,
213
00:12:08,080 --> 00:12:09,790
so UpdateMyPassword,
214
00:12:14,300 --> 00:12:18,190
and now what we need to send in the body is
215
00:12:18,190 --> 00:12:20,103
these three passwords actually,
216
00:12:21,290 --> 00:12:24,817
so it's basically the passwordCurrent,
217
00:12:30,350 --> 00:12:32,050
and for now I'm leaving them empty,
218
00:12:32,050 --> 00:12:35,000
I simply want to put the field names here for now.
219
00:12:35,000 --> 00:12:38,750
So, passwordCurrent then just password,
220
00:12:38,750 --> 00:12:40,503
which is basically the new one,
221
00:12:41,690 --> 00:12:44,110
and then, of course, passwordConfirm.
222
00:12:46,930 --> 00:12:50,320
Okay, and now we actually need to log in as a user
223
00:12:50,320 --> 00:12:53,140
because remember, this only works
224
00:12:53,140 --> 00:12:56,250
if the user is already logged in, all right.
225
00:12:56,250 --> 00:12:59,333
And so, let's actually do it with the administrator here.
226
00:13:00,633 --> 00:13:04,620
And this here is, should be still the current password,
227
00:13:04,620 --> 00:13:07,610
and indeed, we are now logged in.
228
00:13:07,610 --> 00:13:10,520
And remember that this token now gets stored
229
00:13:10,520 --> 00:13:13,313
into the JWT environment variable,
230
00:13:14,240 --> 00:13:17,080
and so, here, in order to authenticate,
231
00:13:17,080 --> 00:13:20,400
let's then actually use that just like we did before.
232
00:13:20,400 --> 00:13:24,710
So, in this authorization tab, we select Bearer Token,
233
00:13:24,710 --> 00:13:27,480
and then it will actually automatically pre-fill
234
00:13:27,480 --> 00:13:29,293
this JWT variable.
235
00:13:30,140 --> 00:13:32,830
All right, and so that's then where actually
236
00:13:32,830 --> 00:13:35,873
the user ID is gonna come from, remember?
237
00:13:37,830 --> 00:13:42,830
Anyway, let's now specify the current password, so pass1234,
238
00:13:42,999 --> 00:13:45,613
and then let's say newpassword, okay?
239
00:13:49,040 --> 00:13:50,713
Copy it and paste it here,
240
00:13:51,560 --> 00:13:54,170
but actually again, I want to start by testing it
241
00:13:54,170 --> 00:13:56,960
with a wrong password confirm,
242
00:13:56,960 --> 00:13:59,810
just to see if our validation is still working,
243
00:13:59,810 --> 00:14:02,720
and now the route is not defined,
244
00:14:02,720 --> 00:14:07,300
but that's simply because we're using the wrong verb here.
245
00:14:07,300 --> 00:14:09,610
Of course, it needs to be patch.
246
00:14:09,610 --> 00:14:11,430
Let's try that again,
247
00:14:11,430 --> 00:14:15,040
but now we get your current password is wrong,
248
00:14:15,040 --> 00:14:18,270
but actually it's not, so it's actually correct.
249
00:14:18,270 --> 00:14:21,163
So, something must be wrong with our code,
250
00:14:22,260 --> 00:14:24,143
so let's try to take a look here.
251
00:14:26,440 --> 00:14:28,440
And yeah, so here is actually the problem
252
00:14:28,440 --> 00:14:32,240
because we do not want to compare or confirm password,
253
00:14:32,240 --> 00:14:34,763
of course, but with the current password.
254
00:14:35,750 --> 00:14:39,780
Okay, so that's just a stupid bug, all right,
255
00:14:39,780 --> 00:14:41,620
and so now it should be working.
256
00:14:41,620 --> 00:14:45,000
So, of course, we want to compare the current password
257
00:14:45,000 --> 00:14:47,050
with the one that is currently stored
258
00:14:47,050 --> 00:14:50,220
in the database, all right.
259
00:14:50,220 --> 00:14:51,503
So, let's try that again,
260
00:14:52,670 --> 00:14:55,460
and so that's the validation error that we were looking for,
261
00:14:55,460 --> 00:14:57,080
so the passwords are not the same
262
00:14:57,080 --> 00:14:59,840
because, indeed, they are not.
263
00:14:59,840 --> 00:15:02,610
And now, before actually updating the password,
264
00:15:02,610 --> 00:15:04,560
let's just take a look at Compass here.
265
00:15:06,070 --> 00:15:08,550
Let's just update it here quickly,
266
00:15:08,550 --> 00:15:11,160
and so, right now, this is the password.
267
00:15:11,160 --> 00:15:15,080
So, ending here is pW1i, okay?
268
00:15:15,080 --> 00:15:17,410
And so, let's update the password now
269
00:15:17,410 --> 00:15:21,333
and see what it's gonna look like afterwards, okay?
270
00:15:23,400 --> 00:15:25,633
So, now everything should be correct.
271
00:15:26,720 --> 00:15:31,720
And, indeed, we get our success and our token, all right.
272
00:15:33,500 --> 00:15:36,000
So, let's confirm that here quickly,
273
00:15:36,000 --> 00:15:38,570
and, indeed, you see that the password changed
274
00:15:38,570 --> 00:15:40,830
and also the current timestamp,
275
00:15:40,830 --> 00:15:44,403
so the time at which basically I'm recording this video.
276
00:15:45,370 --> 00:15:48,670
All right, and now, just like before,
277
00:15:48,670 --> 00:15:51,960
let's actually get this test here.
278
00:15:51,960 --> 00:15:55,433
So, basically storing the token as an environment variable.
279
00:15:59,150 --> 00:16:03,910
So, just so that everything really works here in Postman.
280
00:16:03,910 --> 00:16:06,453
Okay, let's save that actually,
281
00:16:07,590 --> 00:16:12,590
update current user password to make it really explicit,
282
00:16:14,560 --> 00:16:17,780
and yeah, I think that's it.
283
00:16:17,780 --> 00:16:21,090
I think this is all we need to do
284
00:16:21,090 --> 00:16:24,090
in order to update a user's password .
285
00:16:24,090 --> 00:16:27,890
Next up, we will then implement updating of other user data,
286
00:16:27,890 --> 00:16:30,713
so stuff like email or passwords.
22896
Can't find what you're looking for?
Get subtitles in any language from opensubtitles.com, and translate them here.