1
00:00:02,000 --> 00:00:03,000
Okay, so now that we've got

2
00:00:03,000 --> 00:00:06,000
this protection code here in place,

3
00:00:06,000 --> 00:00:09,000
in the next step, we know that this request

4
00:00:09,000 --> 00:00:11,000
is coming from an authenticated user

5
00:00:11,000 --> 00:00:15,000
and we know that it's a request with the right method.

6
00:00:15,000 --> 00:00:17,000
So now we need to extract data

7
00:00:17,000 --> 00:00:21,000
from the incoming request, the old and the new password

8
00:00:21,000 --> 00:00:25,000
and we will also need the email address of that user

9
00:00:25,000 --> 00:00:27,000
because of course, in the database,

10
00:00:27,000 --> 00:00:30,000
we store users with emails and passwords

11
00:00:30,000 --> 00:00:33,000
and if we wanna change the password of a user,

12
00:00:33,000 --> 00:00:35,000
we need that email address of the user as well

13
00:00:35,000 --> 00:00:38,000
to identify that user.

14
00:00:38,000 --> 00:00:41,000
Thankfully, getting that email address is not too difficult

15
00:00:41,000 --> 00:00:44,000
even though it's not part of this form here

16
00:00:44,000 --> 00:00:49,000
because we do encode the email address in our token.

17
00:00:49,000 --> 00:00:53,000
We return that object here in our nextauth file

18
00:00:53,000 --> 00:00:56,000
and that data ends up in the token

19
00:00:56,000 --> 00:00:59,000
and therefore, it's part of that session, which we get here.

20
00:01:00,000 --> 00:01:02,000
So we can get the userEmail

21
00:01:02,000 --> 00:01:07,000
by accessing session.user.email here

22
00:01:09,000 --> 00:01:11,000
and we can then also get the other data,

23
00:01:11,000 --> 00:01:15,000
like the oldPassword by reaching out

24
00:01:15,000 --> 00:01:16,000
to the request

25
00:01:16,000 --> 00:01:19,000
and there the body field as we learned it.

26
00:01:19,000 --> 00:01:22,000
So that's what we also do in the signup.js file

27
00:01:22,000 --> 00:01:23,000
when we create a user.

28
00:01:23,000 --> 00:01:27,000
There we also get the email and password

29
00:01:27,000 --> 00:01:29,000
by diving into the request.body in the end.

30
00:01:31,000 --> 00:01:32,000
And here in change-password,

31
00:01:32,000 --> 00:01:36,000
we could, for example, expect that on the body,

32
00:01:36,000 --> 00:01:39,000
we got a oldPassword field

33
00:01:39,000 --> 00:01:42,000
and then we got the newPassword,

34
00:01:42,000 --> 00:01:44,000
which we get from request.body.newPassword.

35
00:01:45,000 --> 00:01:47,000
Of course, we'll have to make sure

36
00:01:47,000 --> 00:01:49,000
that when we send the request from the client

37
00:01:49,000 --> 00:01:51,000
to the server later,

38
00:01:51,000 --> 00:01:54,000
that we have old and newPassword,

39
00:01:54,000 --> 00:01:57,000
that we have these two fields in the request data,

40
00:01:57,000 --> 00:02:00,000
which we attach to the outgoing request.

41
00:02:01,000 --> 00:02:03,000
And with that, we've got all the data we need.

42
00:02:03,000 --> 00:02:06,000
Now we wanna connect to the database

43
00:02:06,000 --> 00:02:08,000
and find a user by that email

44
00:02:08,000 --> 00:02:10,000
and then once we got that user,

45
00:02:10,000 --> 00:02:13,000
we wanna check if the oldPassword is correct,

46
00:02:13,000 --> 00:02:16,000
so if it matches the password currently stored

47
00:02:16,000 --> 00:02:17,000
in the database

48
00:02:17,000 --> 00:02:18,000
and if that's then the case,

49
00:02:18,000 --> 00:02:21,000
we wanna hash the newPassword

50
00:02:21,000 --> 00:02:25,000
and replace the oldPassword with the new one.

51
00:02:26,000 --> 00:02:31,000
And for this, of course, we can call connectToDatabase again

52
00:02:31,000 --> 00:02:35,000
and import that from our lib/db file like this.

53
00:02:37,000 --> 00:02:39,000
And then here call connectToDatabase

54
00:02:39,000 --> 00:02:41,000
and await this, of course

55
00:02:41,000 --> 00:02:44,000
and here we then get the client.

56
00:02:44,000 --> 00:02:46,000
And then once we got the client,

57
00:02:46,000 --> 00:02:48,000
we can reach out to the database

58
00:02:48,000 --> 00:02:50,000
and then there to the collection

59
00:02:50,000 --> 00:02:54,000
that stores our users, which is the users collection here.

60
00:02:56,000 --> 00:03:00,000
So here we then reach out to the users collection.

61
00:03:00,000 --> 00:03:01,000
usersCollection.

62
00:03:01,000 --> 00:03:05,000
I can store access to that collection in a separate constant

63
00:03:05,000 --> 00:03:10,000
and then we can use that usersCollection to findOne user

64
00:03:10,000 --> 00:03:13,000
by email as we did it before as well

65
00:03:13,000 --> 00:03:15,000
in the authentication code.

66
00:03:15,000 --> 00:03:18,000
There we also find a user by email

67
00:03:18,000 --> 00:03:20,000
and now we're going to do the same thing here.

68
00:03:20,000 --> 00:03:23,000
We look for the email field in our documents

69
00:03:23,000 --> 00:03:25,000
and check if we find one document

70
00:03:25,000 --> 00:03:28,000
where the email address stored in the document

71
00:03:28,000 --> 00:03:31,000
is equal to the userEmail we get from the session.

72
00:03:32,000 --> 00:03:34,000
Now, this will return a promise,

73
00:03:34,000 --> 00:03:39,000
so we await that and then we'll get a user document

74
00:03:39,000 --> 00:03:42,000
or not but if we somehow don't find a user,

75
00:03:42,000 --> 00:03:44,000
something is wrong anyways

76
00:03:44,000 --> 00:03:47,000
because that userEmail is coming from the session,

77
00:03:47,000 --> 00:03:50,000
so it would be strange if we have a logged in user

78
00:03:50,000 --> 00:03:54,000
and yet he or she is missing from the database.

79
00:03:54,000 --> 00:03:57,000
But still, we can also handle that case.

80
00:03:58,000 --> 00:04:00,000
Close our connection here

81
00:04:00,000 --> 00:04:03,000
and then possibly also return some error.

82
00:04:03,000 --> 00:04:05,000
This could be a 404 error

83
00:04:05,000 --> 00:04:10,000
where we say user not found or something like this.

84
00:04:12,000 --> 00:04:14,000
Now, if we make it past this check,

85
00:04:14,000 --> 00:04:15,000
which we typically should,

86
00:04:15,000 --> 00:04:18,000
we can now verify the password.

87
00:04:18,000 --> 00:04:20,000
So we get the currentPassword

88
00:04:20,000 --> 00:04:22,000
by accessing user.password.

89
00:04:22,000 --> 00:04:26,000
So this user document, which we get from the database

90
00:04:26,000 --> 00:04:27,000
and there, the password field,

91
00:04:27,000 --> 00:04:29,000
which is this hashed password.

92
00:04:31,000 --> 00:04:32,000
That's the currentPassword now

93
00:04:32,000 --> 00:04:34,000
and now we wanna verify this

94
00:04:34,000 --> 00:04:37,000
and for that, in the lib folder,

95
00:04:37,000 --> 00:04:42,000
we have this auth.js file with the verifyPassword function.

96
00:04:42,000 --> 00:04:44,000
And I wanna call this function now

97
00:04:46,000 --> 00:04:51,000
and hence, we need to import verifyPassword from lib/auth.

98
00:04:51,000 --> 00:04:53,000
We need to add this import

99
00:04:54,000 --> 00:04:58,000
and with it imported, we can call verifyPassword

100
00:04:58,000 --> 00:05:02,000
and pass in the incoming password,

101
00:05:02,000 --> 00:05:05,000
so the oldPassword in our case,

102
00:05:05,000 --> 00:05:07,000
as a first argument

103
00:05:07,000 --> 00:05:10,000
and then the stored hashed password

104
00:05:10,000 --> 00:05:12,000
to which we wanna compare it.

105
00:05:12,000 --> 00:05:16,000
So this currentPassword here as a second argument.

106
00:05:17,000 --> 00:05:19,000
And we then await this

107
00:05:19,000 --> 00:05:21,000
because that returns a promise

108
00:05:21,000 --> 00:05:24,000
and we get back the answer to the question

109
00:05:24,000 --> 00:05:28,000
whether the passwords are equal or not.

110
00:05:28,000 --> 00:05:30,000
And if they are not equal,

111
00:05:30,000 --> 00:05:32,000
if not passwordsAreEqual,

112
00:05:33,000 --> 00:05:36,000
if that is false, then we know

113
00:05:36,000 --> 00:05:40,000
that the old password entered here simply does not match

114
00:05:40,000 --> 00:05:42,000
the user's password.

115
00:05:42,000 --> 00:05:45,000
And in this case, we don't wanna allow the user

116
00:05:45,000 --> 00:05:47,000
to change the password, of course.

117
00:05:47,000 --> 00:05:49,000
So here we wanna return.

118
00:05:49,000 --> 00:05:54,000
We wanna also close our client connection.

119
00:05:55,000 --> 00:05:57,000
And we wanna send back a response

120
00:05:57,000 --> 00:06:01,000
where the status code could be 403,

121
00:06:01,000 --> 00:06:05,000
not 401 as it was before but 403

122
00:06:05,000 --> 00:06:08,000
where we say you are authenticated,

123
00:06:08,000 --> 00:06:11,000
that's why it's not 401,

124
00:06:11,000 --> 00:06:14,000
but you're not authorized for this operation.

125
00:06:14,000 --> 00:06:17,000
You simply do not have the permissions

126
00:06:17,000 --> 00:06:19,000
to perform this operation

127
00:06:19,000 --> 00:06:21,000
even though you're authenticated.

128
00:06:21,000 --> 00:06:24,000
And in this case, the user doesn't have the permissions

129
00:06:24,000 --> 00:06:26,000
for this specific operation

130
00:06:26,000 --> 00:06:29,000
because the passwords are not equal.

131
00:06:29,000 --> 00:06:33,000
Of course, alternatively, we could also use 422,

132
00:06:33,000 --> 00:06:37,000
which kind of indicates that the user input is incorrect.

133
00:06:37,000 --> 00:06:40,000
And that would be a fair assumption here as well,

134
00:06:40,000 --> 00:06:44,000
that the user simply mistyped the old password.

135
00:06:44,000 --> 00:06:47,000
Ultimately, it's up to you which status code you wanna use

136
00:06:47,000 --> 00:06:50,000
because after all, it will also be you

137
00:06:50,000 --> 00:06:54,000
who has to handle these status codes in the front end code

138
00:06:54,000 --> 00:06:58,000
when it comes to showing an error message to the users.

139
00:06:59,000 --> 00:07:01,000
So here I'll go for 403

140
00:07:01,000 --> 00:07:04,000
and then also attach some data with a message key

141
00:07:04,000 --> 00:07:08,000
where I say invalid password.

142
00:07:09,000 --> 00:07:10,000
Or something like this.

143
00:07:11,000 --> 00:07:14,000
Now, if we do make it past this if check though,

144
00:07:14,000 --> 00:07:17,000
then we know that the passwords are equal

145
00:07:17,000 --> 00:07:20,000
and then we can replace the oldPassword in the database

146
00:07:20,000 --> 00:07:22,000
with the new one.

147
00:07:22,000 --> 00:07:25,000
Now, for this we can use our usersCollection again

148
00:07:26,000 --> 00:07:31,000
and call updateOne to update one document

149
00:07:31,000 --> 00:07:34,000
and for that, we now need to pass in our first argument

150
00:07:34,000 --> 00:07:38,000
where we identify the document that should be updated

151
00:07:38,000 --> 00:07:39,000
and in this case, that's the document

152
00:07:39,000 --> 00:07:42,000
where the email matches the userEmail.

153
00:07:43,000 --> 00:07:47,000
So the same filter as we set it up here for finding a user.

154
00:07:49,000 --> 00:07:52,000
But then here we also need to pass in a second argument

155
00:07:52,000 --> 00:07:55,000
where we describe the update.

156
00:07:55,000 --> 00:07:57,000
Now, for describing the update,

157
00:07:57,000 --> 00:08:00,000
we also pass in a JavaScript object

158
00:08:00,000 --> 00:08:02,000
as a second argument

159
00:08:02,000 --> 00:08:07,000
and in there, we add the special $set key.

160
00:08:08,000 --> 00:08:10,000
This is a special key which will be identified

161
00:08:10,000 --> 00:08:11,000
and understood by MongoDB

162
00:08:13,000 --> 00:08:17,000
and $set then wants a nested object as a value

163
00:08:17,000 --> 00:08:20,000
where we just set the properties of the document

164
00:08:20,000 --> 00:08:22,000
that should change.

165
00:08:22,000 --> 00:08:23,000
So in this case, for example,

166
00:08:23,000 --> 00:08:25,000
I don't wanna change the email,

167
00:08:25,000 --> 00:08:26,000
I don't wanna change the ID,

168
00:08:26,000 --> 00:08:28,000
I wanna change the password.

169
00:08:28,000 --> 00:08:32,000
So as a value for $set, I have an object

170
00:08:32,000 --> 00:08:33,000
where I set password

171
00:08:33,000 --> 00:08:36,000
and now this key here has to match one

172
00:08:36,000 --> 00:08:38,000
of the keys of your document

173
00:08:38,000 --> 00:08:41,000
or it's added as a new key if it doesn't,

174
00:08:41,000 --> 00:08:42,000
which I don't want here.

175
00:08:42,000 --> 00:08:45,000
So here I'll set password to the newPassword

176
00:08:47,000 --> 00:08:50,000
but of course, as you learned, not like this.

177
00:08:50,000 --> 00:08:53,000
Instead, we wanna hash that newPassword first

178
00:08:53,000 --> 00:08:55,000
because if the password has changed,

179
00:08:55,000 --> 00:08:59,000
we, of course, still don't wanna store plain text passwords

180
00:08:59,000 --> 00:09:00,000
in the database.

181
00:09:01,000 --> 00:09:05,000
And therefore here, I'll now create my hashedPassword

182
00:09:07,000 --> 00:09:08,000
by calling hashPassword,

183
00:09:10,000 --> 00:09:12,000
which is a function we have to import

184
00:09:12,000 --> 00:09:15,000
from the lib/auth file as well.

185
00:09:17,000 --> 00:09:19,000
And when we call hashPassword,

186
00:09:19,000 --> 00:09:22,000
we pass the newPassword, the plain text password

187
00:09:22,000 --> 00:09:26,000
as a argument and then await this operation,

188
00:09:26,000 --> 00:09:28,000
since it returns a promise,

189
00:09:28,000 --> 00:09:30,000
and we then get this hashedPassword

190
00:09:30,000 --> 00:09:33,000
and that's then the password we wanna set

191
00:09:33,000 --> 00:09:35,000
for the updateOne operation.

192
00:09:35,000 --> 00:09:38,000
And this will now update the user in the database.

193
00:09:39,000 --> 00:09:42,000
Now, we can also await this operation

194
00:09:42,000 --> 00:09:45,000
and we can get the result and do something with it

195
00:09:45,000 --> 00:09:46,000
if we want to.

196
00:09:46,000 --> 00:09:50,000
Here I don't actually need it but still, I'll get it.

197
00:09:50,000 --> 00:09:53,000
And we can also add error handling as we did it before

198
00:09:53,000 --> 00:09:55,000
in the course but for the moment,

199
00:09:55,000 --> 00:09:57,000
I'll ignore all of that.

200
00:09:57,000 --> 00:10:00,000
I'll then just close the client connection

201
00:10:00,000 --> 00:10:02,000
and then send back a response

202
00:10:02,000 --> 00:10:04,000
with a status code of 200

203
00:10:04,000 --> 00:10:09,000
where we, for example, say Password updated.

204
00:10:11,000 --> 00:10:12,000
Like this.

205
00:10:12,000 --> 00:10:14,000
And now with all that in place,

206
00:10:14,000 --> 00:10:16,000
with all that code added,

207
00:10:16,000 --> 00:10:20,000
we should have the code that does change the password

208
00:10:20,000 --> 00:10:22,000
of an authenticated user

209
00:10:22,000 --> 00:10:25,000
and therefore, now with all that in place,

210
00:10:25,000 --> 00:10:27,000
we now need to go to the front end

211
00:10:27,000 --> 00:10:29,000
and work on the front end code

212
00:10:29,000 --> 00:10:34,000
to send a HTTP request to this newly added API route.

