1
00:00:03,650 --> 00:00:08,385
We had already developed a full-fledged REST API server

2
00:00:08,385 --> 00:00:12,485
using Express and MongoDB as part of this course.

3
00:00:12,485 --> 00:00:16,965
In order for that server to be able to communicate meaningfully with our client,

4
00:00:16,965 --> 00:00:19,590
we will make a few minor adjustments to it

5
00:00:19,590 --> 00:00:22,440
so that it returns the right kind of data so that

6
00:00:22,440 --> 00:00:24,780
our client implementation can work more

7
00:00:24,780 --> 00:00:28,935
efficiently with the data returned from our server site.

8
00:00:28,935 --> 00:00:30,410
So, to do that,

9
00:00:30,410 --> 00:00:36,580
let's work on a few adjustments to our server site in this exercise.

10
00:00:36,580 --> 00:00:39,215
Before you start this exercise,

11
00:00:39,215 --> 00:00:42,410
I am assuming that you have not done

12
00:00:42,410 --> 00:00:46,430
the previous lesson on integrating the angular client and

13
00:00:46,430 --> 00:00:55,395
the server because you are doing this lesson coming through the React specialization.

14
00:00:55,395 --> 00:01:01,190
So, the changes that I will make to the server will assume that

15
00:01:01,190 --> 00:01:07,430
the version of the server that you're modifying is before the previous lesson.

16
00:01:07,430 --> 00:01:11,540
In case you have done that lesson on angular client,

17
00:01:11,540 --> 00:01:16,505
some of the changes that you have done to your server will be repeated again

18
00:01:16,505 --> 00:01:22,495
in this exercise so you can skip over that part of the changes.

19
00:01:22,495 --> 00:01:26,055
Go in to our server in the editor.

20
00:01:26,055 --> 00:01:29,125
Before we start working on the server,

21
00:01:29,125 --> 00:01:33,530
I would suggest that you download all the images that I have

22
00:01:33,530 --> 00:01:38,380
provided as a zip file in the exercise resources called images.zip.

23
00:01:38,380 --> 00:01:43,160
Unzip the file and then obtain all the images from there and then copy those images

24
00:01:43,160 --> 00:01:48,290
into the public images folder in our server.

25
00:01:48,290 --> 00:01:55,010
So, you see that here I have copied all the images into my public images folder here

26
00:01:55,010 --> 00:01:58,160
already because our server is the one that is going to

27
00:01:58,160 --> 00:02:02,275
serve up all these images for our client application.

28
00:02:02,275 --> 00:02:07,835
Next, we go to the CORS and adjust the whitelist here.

29
00:02:07,835 --> 00:02:11,565
So, for our React client application,

30
00:02:11,565 --> 00:02:15,275
if we started up with the yarn start command,

31
00:02:15,275 --> 00:02:18,470
it runs at your computer name:3001.

32
00:02:18,470 --> 00:02:22,040
So, any request coming in from our location to

33
00:02:22,040 --> 00:02:25,760
the server will carry that as the origin there.

34
00:02:25,760 --> 00:02:30,380
So that is why I am going to add that into my whitelist so that

35
00:02:30,380 --> 00:02:35,390
any CORS problems will be addressed automatically.

36
00:02:35,390 --> 00:02:40,985
So, going into the cors.js file in my whitelist here,

37
00:02:40,985 --> 00:02:49,460
let me add in the http://my computer's

38
00:02:49,460 --> 00:02:55,640
name:3001 and this is

39
00:02:55,640 --> 00:02:58,610
the origin from which my client will

40
00:02:58,610 --> 00:03:02,075
be originating the requests that come to this server.

41
00:03:02,075 --> 00:03:07,075
So, that way my CORS would not cause problems for my client.

42
00:03:07,075 --> 00:03:11,690
Next, we need to update a few of the routes to

43
00:03:11,690 --> 00:03:17,690
handle the query parameters and also a few minor other adjustments.

44
00:03:17,690 --> 00:03:21,280
Let me start with the promoRouter.js file.

45
00:03:21,280 --> 00:03:25,010
That is simple to get updated.

46
00:03:25,010 --> 00:03:27,570
So, going into the promoRouter.js file,

47
00:03:27,570 --> 00:03:32,360
in the promoRouter file for the get request that we get

48
00:03:32,360 --> 00:03:37,610
here instead of doing promotions find with an empty JavaScript object,

49
00:03:37,610 --> 00:03:47,320
here I would supply the req.query as the parameter to the promotions find here,

50
00:03:47,320 --> 00:03:49,680
same thing with the leader router also.

51
00:03:49,680 --> 00:03:52,745
So, let me go to the leaderRouter.js file.

52
00:03:52,745 --> 00:03:54,815
In the leader router also,

53
00:03:54,815 --> 00:04:00,545
here where you find Leaders.find with the empty JavaScript object instead

54
00:04:00,545 --> 00:04:06,685
replace that with the req.query so that the query parameters will be passed in.

55
00:04:06,685 --> 00:04:14,260
So, this is where we will pass in the featured:true as the query parameter here.

56
00:04:14,260 --> 00:04:16,945
Now, having adjusted these two,

57
00:04:16,945 --> 00:04:19,340
let's now work on the dish router.

58
00:04:19,340 --> 00:04:22,115
So, go into dishRouter.js file,

59
00:04:22,115 --> 00:04:26,310
even in the dish router also the same update here.

60
00:04:26,310 --> 00:04:31,200
So, go into this Dishes.find in the get method here,

61
00:04:31,200 --> 00:04:33,945
change that to req.query.

62
00:04:33,945 --> 00:04:38,070
So, with this, my dish router update has been completed.

63
00:04:38,070 --> 00:04:42,085
So, we have now updated the promo router, the leader,

64
00:04:42,085 --> 00:04:43,850
and the dish router,

65
00:04:43,850 --> 00:04:48,050
then we will move on to update the favorite router.

66
00:04:48,050 --> 00:04:54,380
Now, you would have implemented the favorite router as part of your fourth assignment.

67
00:04:54,380 --> 00:04:56,530
Now, in the favorite router,

68
00:04:56,530 --> 00:04:58,910
you will see that for the favorite router,

69
00:04:58,910 --> 00:05:01,010
I'm not showing you the remaining part because that

70
00:05:01,010 --> 00:05:03,435
you should have done as part of your assignment.

71
00:05:03,435 --> 00:05:11,520
First, let me draw your attention to the get method for the favoriteRouter.route:dishId.

72
00:05:11,520 --> 00:05:17,405
Now I'm going to use this get method to just check to ensure that

73
00:05:17,405 --> 00:05:25,460
the specific dish with the dish Id is already a favorite for the user.

74
00:05:25,460 --> 00:05:29,130
So, instead of simply saying getoperation.supported,

75
00:05:29,130 --> 00:05:36,165
I am just going to leverage the presence of this get operation and then we'll say,

76
00:05:36,165 --> 00:05:47,500
Favorites.findOne and we'll say user: req.user._id.

77
00:05:49,220 --> 00:05:59,340
So, we will find the favorites for that particular user and then we'll say then

78
00:06:03,070 --> 00:06:25,530
favorites and catch error next.

79
00:06:25,530 --> 00:06:35,265
Then similarly here, we will add in the err here, next err here.

80
00:06:35,265 --> 00:06:37,380
So, inside this then,

81
00:06:37,380 --> 00:06:39,495
when we get the favorites,

82
00:06:39,495 --> 00:06:45,360
then we will check if not favorites.

83
00:06:45,360 --> 00:06:47,690
So, if there are no favorites for

84
00:06:47,690 --> 00:06:53,900
this user then obviously the dish that we are checking for doesn't exist,

85
00:06:53,900 --> 00:07:07,520
so we'll return res.statusCode 200,

86
00:07:07,520 --> 00:07:14,370
setHeader, Content-Type,

87
00:07:17,230 --> 00:07:36,735
application/json and then we'll return saying exists false.

88
00:07:36,735 --> 00:07:44,215
What we are specifying here is that if they get is done to this end point with a dish Id,

89
00:07:44,215 --> 00:07:52,835
this exists flag here will be set to true if this dish is part of my favorites.

90
00:07:52,835 --> 00:07:55,290
If this dish is not part of my favorites,

91
00:07:55,290 --> 00:07:58,100
I will set there exists flag to false.

92
00:07:58,100 --> 00:08:01,190
So here, you see that since I don't have any favorites so

93
00:08:01,190 --> 00:08:04,770
exists should be automatically false at this point.

94
00:08:04,770 --> 00:08:13,020
So, we'll say exists false and then we will return the favorites here.

95
00:08:13,180 --> 00:08:19,090
Well, obviously, in this case the favorites would be null at this point.

96
00:08:19,090 --> 00:08:26,440
Otherwise, so which means that favorites is not null,

97
00:08:26,440 --> 00:08:32,750
so we'll say if favorites.dishes.indexOf.

98
00:08:36,840 --> 00:08:45,995
So, we're going to be searching for req.params.dishId.

99
00:08:45,995 --> 00:08:51,220
So, we're going to search this favorites dishes array to

100
00:08:51,220 --> 00:08:56,605
see if this dish exists in there and if it doesn't exist,

101
00:08:56,605 --> 00:09:00,525
obviously this will return a negative index here.

102
00:09:00,525 --> 00:09:02,340
In that case also,

103
00:09:02,340 --> 00:09:05,440
I will return exactly the same as here.

104
00:09:05,440 --> 00:09:08,630
So, if it returns a negative index then that means that even

105
00:09:08,630 --> 00:09:12,260
though this particular user has a set of favorites,

106
00:09:12,260 --> 00:09:16,190
this specific dish doesn't exist in

107
00:09:16,190 --> 00:09:22,340
the list of his or her favorites so that's why it'll return exists false here.

108
00:09:22,340 --> 00:09:30,255
Now, otherwise that means that the dish exists in the list of favorites.

109
00:09:30,255 --> 00:09:31,859
So, in this case,

110
00:09:31,859 --> 00:09:36,670
I will return status code 200 exists is true.

111
00:09:36,670 --> 00:09:43,825
So that way, when the user performs a get operation on this endpoint with

112
00:09:43,825 --> 00:09:52,015
the /favorites/dishId where the dish Id is supplied as the parameter here,

113
00:09:52,015 --> 00:09:55,630
as the request parameter here,

114
00:09:55,630 --> 00:10:00,650
then we will check to see whether that dish exists in the favorites.

115
00:10:00,650 --> 00:10:05,775
If none of the favorites exists for this user then we'll return an exists false.

116
00:10:05,775 --> 00:10:08,120
Similarly, if the favorites exists but

117
00:10:08,120 --> 00:10:12,320
that particular dish doesn't exist in the favorites then we'll return false,

118
00:10:12,320 --> 00:10:13,910
otherwise we will return true.

119
00:10:13,910 --> 00:10:20,260
So this exists flag can be used by my client to check to see if this dish is

120
00:10:20,260 --> 00:10:27,755
part of the list of favorite dishes for this user or not.

121
00:10:27,755 --> 00:10:30,139
Also while we are in favorites,

122
00:10:30,139 --> 00:10:33,410
whenever we make any changes to the favorites,

123
00:10:33,410 --> 00:10:37,870
we want to be able to populate the user and dishes information,

124
00:10:37,870 --> 00:10:39,535
the favorites, before we return.

125
00:10:39,535 --> 00:10:43,240
For example, in the post that we do,

126
00:10:43,240 --> 00:10:48,470
when we save the favorites then at this point,

127
00:10:48,470 --> 00:10:55,470
we would like to first do favorites.

128
00:10:55,620 --> 00:11:06,380
FindById, so because we just made the changes we'll say favorite_id

129
00:11:07,740 --> 00:11:15,325
and we'll populate both the user and also

130
00:11:15,325 --> 00:11:25,490
populate the dishes in the favorites.

131
00:11:25,740 --> 00:11:32,420
Then when the favorites is returned,

132
00:11:32,610 --> 00:11:36,940
we'll return that favorites instead.

133
00:11:36,940 --> 00:11:40,440
So, let me make this change here.

134
00:11:40,440 --> 00:11:46,910
So, we will cut this out from here and then inside the then,

135
00:11:46,910 --> 00:11:49,645
we'll return the favorites.

136
00:11:49,645 --> 00:11:53,510
After we save the favorites,

137
00:11:53,510 --> 00:11:54,980
then we'll search for it,

138
00:11:54,980 --> 00:11:58,285
for the favoriteById and then return

139
00:11:58,285 --> 00:12:03,940
that favorite here so we'll say then favorite return and status code.

140
00:12:03,940 --> 00:12:05,355
This change we should make.

141
00:12:05,355 --> 00:12:08,180
If you have already implemented this in your favorites,

142
00:12:08,180 --> 00:12:09,760
then you don't need to make this change.

143
00:12:09,760 --> 00:12:13,310
But what we are doing is whenever we make changes to the favorites,

144
00:12:13,310 --> 00:12:17,380
we'll populate both the user and dishes information and then return this value

145
00:12:17,380 --> 00:12:22,360
because our React client expects this to be there.

146
00:12:22,360 --> 00:12:24,685
Now, the same kind of change,

147
00:12:24,685 --> 00:12:28,350
we will need to make variable b, save the changes.

148
00:12:28,350 --> 00:12:33,125
So in the post here,

149
00:12:33,125 --> 00:12:36,090
we'll make a change to that,

150
00:12:36,090 --> 00:12:42,705
so we'll say favorites.save and then we'll do favorites.findById and make that change.

151
00:12:42,705 --> 00:12:45,210
Similarly, under the dish id,

152
00:12:45,210 --> 00:12:47,095
also in the post,

153
00:12:47,095 --> 00:12:51,070
you will be similarly, whenever you make changes to the favorites,

154
00:12:51,070 --> 00:12:57,715
will first look for it and then populate both the user and dishes and then return it,

155
00:12:57,715 --> 00:12:59,910
and then similarly in the else part.

156
00:12:59,910 --> 00:13:06,290
So, you must have implemented this in your fourth assignment.

157
00:13:06,290 --> 00:13:09,010
So, make this additional change where you will populate

158
00:13:09,010 --> 00:13:12,350
the user and dishes before you return the value.

159
00:13:12,350 --> 00:13:14,685
Also with the delete,

160
00:13:14,685 --> 00:13:17,385
we'll do the same changes here.

161
00:13:17,385 --> 00:13:19,890
So, you notice that in the delete,

162
00:13:19,890 --> 00:13:21,830
I have already made this change here.

163
00:13:21,830 --> 00:13:27,085
So, after we save the changes to the favorites,

164
00:13:27,085 --> 00:13:29,480
we'll then search for the favorites and then

165
00:13:29,480 --> 00:13:33,465
return after populating both the user and dishes and the favorites.

166
00:13:33,465 --> 00:13:36,505
This is what our React client expects us to do.

167
00:13:36,505 --> 00:13:38,145
So, even for the delete,

168
00:13:38,145 --> 00:13:39,995
we'll do the same changes.

169
00:13:39,995 --> 00:13:44,115
Now, with this, my favorite router is updated

170
00:13:44,115 --> 00:13:48,575
so we'll proceed ahead to update users.js next.

171
00:13:48,575 --> 00:13:52,370
Finally, we'll update the users.js file.

172
00:13:52,370 --> 00:13:57,060
Now, in the users.js file we need to add in

173
00:13:57,060 --> 00:14:05,245
another router.options field here,

174
00:14:05,245 --> 00:14:10,610
because sometimes a post request as you saw

175
00:14:10,610 --> 00:14:16,315
with the login will send the options first to check,

176
00:14:16,315 --> 00:14:21,610
especially with cars, whether the post request will be allowed.

177
00:14:21,610 --> 00:14:30,080
So that's why we will check course with options here and then

178
00:14:31,860 --> 00:14:35,450
we'll simply return

179
00:14:39,960 --> 00:14:43,045
a status message

180
00:14:43,045 --> 00:14:46,180
of 200 in response to that.

181
00:14:46,180 --> 00:14:52,960
For any endpoint under users if we receive the options,

182
00:14:52,960 --> 00:14:56,530
we'll simply return a status 200 here.

183
00:14:56,530 --> 00:15:03,580
Now the login function that we had implemented earlier,

184
00:15:03,580 --> 00:15:07,470
we had simply done passport.authenticate

185
00:15:07,470 --> 00:15:12,930
local here and the we checked for the remaining values here.

186
00:15:12,930 --> 00:15:15,215
Now, this passport.authenticate local,

187
00:15:15,215 --> 00:15:17,600
if the user doesn't get authenticated,

188
00:15:17,600 --> 00:15:21,800
it simply returns an unauthorized in the reply message.

189
00:15:21,800 --> 00:15:28,380
Now that may not be very meaningful for the client side to display this information,

190
00:15:28,380 --> 00:15:30,480
so that is why we will enhance

191
00:15:30,480 --> 00:15:36,310
this router post login method

192
00:15:36,310 --> 00:15:41,765
such that the authentication will return more meaningful information at this point.

193
00:15:41,765 --> 00:15:43,210
So to do that,

194
00:15:43,210 --> 00:15:49,395
we are not going to be doing the passport.authenticate in here,

195
00:15:49,395 --> 00:15:51,955
instead we will take.

196
00:15:51,955 --> 00:15:55,140
So, let me remove that from there and then you will see

197
00:15:55,140 --> 00:15:58,930
how I will update the router post here.

198
00:15:58,930 --> 00:16:08,620
So, we'll see course with options and then we'll include the req,

199
00:16:08,620 --> 00:16:12,160
res and next here.

200
00:16:12,160 --> 00:16:16,885
Inside this req, res and next here,

201
00:16:16,885 --> 00:16:27,954
passport.authenticate will call this with local.

202
00:16:27,954 --> 00:16:31,210
Now, when we call this with local,

203
00:16:31,210 --> 00:16:34,970
if authentication error occurs,

204
00:16:34,970 --> 00:16:38,240
the passport.authenticate can be made to return

205
00:16:38,240 --> 00:16:44,230
the error value and also it will return the user if there is

206
00:16:44,230 --> 00:16:48,960
no error and a third parameter called info

207
00:16:48,960 --> 00:16:54,000
which will carry additional info that might be parsed back to the user.

208
00:16:54,000 --> 00:16:56,580
This error will be returned when there is

209
00:16:56,580 --> 00:16:59,950
a genuine error that occurs in the passport.authenticate.

210
00:16:59,950 --> 00:17:03,400
But if the user information

211
00:17:03,400 --> 00:17:07,645
is sent into passport.authenticate but the user doesn't exist,

212
00:17:07,645 --> 00:17:10,490
then that that is not counted as an error.

213
00:17:10,490 --> 00:17:14,690
Instead, it'll be counted as user doesn't exist and

214
00:17:14,690 --> 00:17:19,305
that information is parsed back in the info object that comes in.

215
00:17:19,305 --> 00:17:21,500
So, the error will be returned when there is

216
00:17:21,500 --> 00:17:24,925
a genuine error that occurs during the authentication process,

217
00:17:24,925 --> 00:17:30,820
but the info will contain information if the user doesn't exist.

218
00:17:30,820 --> 00:17:36,920
So, the passport.authenticate is passing back a message saying that

219
00:17:36,920 --> 00:17:39,575
the user doesn't exist or either the username

220
00:17:39,575 --> 00:17:42,850
is incorrect or the password is incorrect and so on.

221
00:17:42,850 --> 00:17:46,870
So, that information will be passed in in the info message.

222
00:17:46,870 --> 00:17:49,230
Now we will see how this is useful to

223
00:17:49,230 --> 00:17:52,060
us when we look at the client side a little bit later.

224
00:17:52,060 --> 00:17:55,400
So, in this situation,

225
00:17:55,400 --> 00:18:01,455
we will handle this as follows,

226
00:18:01,455 --> 00:18:06,810
and not only that when we call this passport.authenticate,

227
00:18:06,810 --> 00:18:10,220
we also need to pass in a req,

228
00:18:10,220 --> 00:18:15,080
res, next as the three parameters to it.

229
00:18:15,080 --> 00:18:20,130
So, this is the structure when you need to call passport.authenticate and expect it to

230
00:18:20,130 --> 00:18:25,270
pass you back information like this as a callback method here,

231
00:18:25,270 --> 00:18:27,630
so you also need to supply this req, res,

232
00:18:27,630 --> 00:18:30,250
next right there too.

233
00:18:30,250 --> 00:18:32,270
Now, if this occurs,

234
00:18:32,270 --> 00:18:36,780
so we'll say if err,

235
00:18:36,780 --> 00:18:40,425
so if there's an error that occurs,

236
00:18:40,425 --> 00:18:45,395
we'll say return next err and then let

237
00:18:45,395 --> 00:18:51,480
the error handler of our express router and take care of that.

238
00:18:51,480 --> 00:18:56,755
Now, we will consider other situations, if not user.

239
00:18:56,755 --> 00:18:59,630
So, if we have reached this point,

240
00:18:59,630 --> 00:19:02,580
then that means that it was not an error that occurred

241
00:19:02,580 --> 00:19:05,615
but instead perhaps the user could not be found.

242
00:19:05,615 --> 00:19:07,100
If the user is not found,

243
00:19:07,100 --> 00:19:11,190
then the user here will be set to null in this case.

244
00:19:11,190 --> 00:19:14,634
So, in that situation,

245
00:19:14,634 --> 00:19:17,375
if the user doesn't exist,

246
00:19:17,375 --> 00:19:23,680
then we need to be able to pass information back to the server side.

247
00:19:23,680 --> 00:19:28,435
So, what we will do is we will pass in this information in this format.

248
00:19:28,435 --> 00:19:32,020
So, I'm going to cut this out from here and

249
00:19:32,020 --> 00:19:36,640
then paste it in here and then we will edit this.

250
00:19:36,640 --> 00:19:40,704
So, if the user is null,

251
00:19:40,704 --> 00:19:45,830
then we will send back a status code as 401 which means

252
00:19:45,830 --> 00:19:53,975
unauthorized and then we will send back information success false,

253
00:19:53,975 --> 00:19:57,405
and then we will not be passing back the token,

254
00:19:57,405 --> 00:20:00,795
we'll pass back the status message.

255
00:20:00,795 --> 00:20:03,135
So, here we'll say

256
00:20:03,135 --> 00:20:12,670
'Login Unsuccessful' and then the third information,

257
00:20:12,670 --> 00:20:18,070
we will pass this info that object that we received here as

258
00:20:18,070 --> 00:20:25,635
the third part in the reply message that we send back from our server here.

259
00:20:25,635 --> 00:20:28,935
So, the success flag will be set to false,

260
00:20:28,935 --> 00:20:32,385
the status will be set Login Unsuccessful and

261
00:20:32,385 --> 00:20:36,725
the error information that is passed in the info will be passed back.

262
00:20:36,725 --> 00:20:39,855
Now, note that this situation will occur if

263
00:20:39,855 --> 00:20:43,125
either the username and the password is incorrect,

264
00:20:43,125 --> 00:20:48,600
and so this is not an error in the error sense but the fact that

265
00:20:48,600 --> 00:20:54,040
the authenticate could not find either the user or the password of the user is incorrect.

266
00:20:54,040 --> 00:20:58,530
So, that information will be encoded into the info that comes in and so that I will

267
00:20:58,530 --> 00:21:04,590
pass back as an error to my client side.

268
00:21:04,590 --> 00:21:09,615
The otherwise part

269
00:21:09,615 --> 00:21:15,355
is handled as req.logIn.

270
00:21:15,355 --> 00:21:17,220
So, if this is successful,

271
00:21:17,220 --> 00:21:22,710
the passport.authenticate we'll add this method called req.logIn to the user.

272
00:21:22,710 --> 00:21:24,340
So, at this point,

273
00:21:24,340 --> 00:21:27,950
we will just simply pass in the user object that we've obtained.

274
00:21:27,950 --> 00:21:31,055
So here, if we have reached this point,

275
00:21:31,055 --> 00:21:36,195
then that means that the user object is not null and also no error occurred,

276
00:21:36,195 --> 00:21:40,090
so that means that the user can be logged in.

277
00:21:41,080 --> 00:21:44,550
So, we'll say err,

278
00:21:48,960 --> 00:21:51,460
we'll try to login the user.

279
00:21:51,460 --> 00:21:58,000
So, we'll say if err and

280
00:21:58,000 --> 00:22:05,345
then we will pass back the same kind of error information that we did here.

281
00:22:05,345 --> 00:22:09,840
So in this case, if error,

282
00:22:13,290 --> 00:22:19,430
then we will pass back a status code as 401 and we'll say success

283
00:22:19,430 --> 00:22:25,125
is false and status as Login Unsuccessful,

284
00:22:25,125 --> 00:22:28,340
and then the error information,

285
00:22:29,280 --> 00:22:31,840
instead of the info,

286
00:22:31,840 --> 00:22:42,380
we will pass in 'Could not log in user".

287
00:22:42,380 --> 00:22:48,960
So, that is the message that we'll pass back here if the error occurs.

288
00:22:48,960 --> 00:22:53,200
Otherwise, we would be down below here.

289
00:22:53,200 --> 00:22:55,960
So, at this point,

290
00:22:55,960 --> 00:22:59,440
we would be able to generate the token.

291
00:22:59,440 --> 00:23:02,495
So, if we have reached up to this point,

292
00:23:02,495 --> 00:23:06,370
that means that the user has successfully logged in,

293
00:23:06,370 --> 00:23:08,430
and so we can now generate the token.

294
00:23:08,430 --> 00:23:12,705
So, we'll generate the token based upon the user's ID,

295
00:23:12,705 --> 00:23:18,350
and then we'll pass back the token back to the user.

296
00:23:18,350 --> 00:23:21,635
So, here, we will say var token,

297
00:23:21,635 --> 00:23:30,730
and then we can say res.statusCode is 200 and then res.json success true,

298
00:23:30,730 --> 00:23:33,600
so, which means that the user successfully logged in.

299
00:23:33,600 --> 00:23:38,490
So, the status would be login successful.

300
00:23:38,490 --> 00:23:40,605
Then, the third part,

301
00:23:40,605 --> 00:23:42,360
instead of the error,

302
00:23:42,360 --> 00:23:46,200
I will pass the token back to the user.

303
00:23:46,200 --> 00:23:48,760
So, we'll say token,

304
00:23:51,100 --> 00:23:54,675
this token which we just obtained earlier.

305
00:23:54,675 --> 00:24:01,030
So, that token will be passed in as the token property of the reply message.

306
00:24:01,030 --> 00:24:04,560
So, here, notice that the success is set to true, so,

307
00:24:04,560 --> 00:24:08,340
which means that the user successfully logged in,

308
00:24:08,340 --> 00:24:12,290
and so the user can proceed further at this point.

309
00:24:12,290 --> 00:24:19,050
This has to be done inside the req.logIn here.

310
00:24:19,820 --> 00:24:22,970
So, at this point,

311
00:24:22,970 --> 00:24:27,180
we will close the req.logIn.

312
00:24:27,180 --> 00:24:33,735
So, notice that this is inside this req.logIn here.

313
00:24:33,735 --> 00:24:37,320
So, in there, we will pass these three back.

314
00:24:37,320 --> 00:24:41,370
So, let me just indent these three lines in.

315
00:24:41,720 --> 00:24:48,850
So, that is how we would handle the user's logging method.

316
00:24:48,850 --> 00:24:52,230
So, again, reviewing this code one more time.

317
00:24:52,230 --> 00:24:53,950
So, we'll do router post,

318
00:24:53,950 --> 00:24:56,815
but instead of doing passport authenticate right there,

319
00:24:56,815 --> 00:24:58,960
we will say req, res,

320
00:24:58,960 --> 00:25:01,240
next, and then inside here,

321
00:25:01,240 --> 00:25:04,285
we'll do a passport authenticate for the local,

322
00:25:04,285 --> 00:25:06,560
and this authenticate will pass back.

323
00:25:06,560 --> 00:25:09,250
So, we can supply a callback function to that,

324
00:25:09,250 --> 00:25:11,810
and this callback function will return either the error,

325
00:25:11,810 --> 00:25:14,730
the user, or the info here.

326
00:25:14,730 --> 00:25:16,300
So, if it is an error,

327
00:25:16,300 --> 00:25:20,735
we'll just allow the express error handler to take care of that.

328
00:25:20,735 --> 00:25:22,730
If the user is null,

329
00:25:22,730 --> 00:25:26,940
then that means that the user login was unsuccessful,

330
00:25:26,940 --> 00:25:29,730
and the reason for that will be in the info.

331
00:25:29,730 --> 00:25:36,870
So, that will pass back as the info error in the reply message here.

332
00:25:36,870 --> 00:25:38,790
If we come up to this point,

333
00:25:38,790 --> 00:25:43,555
then the user is successfully verified.

334
00:25:43,555 --> 00:25:45,400
So, then we will login the user.

335
00:25:45,400 --> 00:25:47,630
So, the passport authenticate,

336
00:25:47,630 --> 00:25:53,385
we'll add in this method called login to the req, the request message.

337
00:25:53,385 --> 00:25:56,770
So, we can call the login with the user.

338
00:25:56,770 --> 00:25:59,355
If this returns an error,

339
00:25:59,355 --> 00:26:03,105
then we will return the error here appropriately.

340
00:26:03,105 --> 00:26:08,590
If not, then we will have reached the point where the user is successfully authenticated.

341
00:26:08,590 --> 00:26:12,630
So, we can generate the JSON Web Token here and then return

342
00:26:12,630 --> 00:26:18,315
the JSON Web Token to the user to confirm that the user is successfully logged in.

343
00:26:18,315 --> 00:26:21,545
So, that is the set of steps that we're going to use here.

344
00:26:21,545 --> 00:26:25,735
Now, the reason why I do a more elaborate way of handling it is that

345
00:26:25,735 --> 00:26:30,035
I want to distinguish between the situation where a genuine error

346
00:26:30,035 --> 00:26:34,170
occurs during the authentication process as opposed to the situation

347
00:26:34,170 --> 00:26:39,095
where the user name is invalid or the password is invalid.

348
00:26:39,095 --> 00:26:42,860
So, those two cases will be handled by this situation,

349
00:26:42,860 --> 00:26:46,550
where the info will carry the information back to us.

350
00:26:46,550 --> 00:26:48,900
So, that's not a error per se,

351
00:26:48,900 --> 00:26:52,090
but that's situation where the user is

352
00:26:52,090 --> 00:26:55,710
not a valid user or the user's password is not valid.

353
00:26:55,710 --> 00:27:01,070
So, that's how we will handle the user's login process.

354
00:27:01,070 --> 00:27:03,660
In addition, I will add in

355
00:27:03,660 --> 00:27:14,825
one more method here called checkJWTToken.

356
00:27:14,825 --> 00:27:21,100
It is quite possible that while the client has logged in and obtain the JSON Web Token,

357
00:27:21,100 --> 00:27:24,855
sometime later, the JSON Web Token may expire.

358
00:27:24,855 --> 00:27:32,840
So, if the user tries to access from the client side with an expired token to the server,

359
00:27:32,840 --> 00:27:35,610
then the server will not be able to authenticate the user.

360
00:27:35,610 --> 00:27:37,780
So, at periodic intervals,

361
00:27:37,780 --> 00:27:42,180
we may wish to cross-check to make sure that the JSON Web Token is still valid.

362
00:27:42,180 --> 00:27:44,975
So, that is the reason why I am including this,

363
00:27:44,975 --> 00:27:49,620
another endpoint called checkJWTToken.

364
00:27:49,620 --> 00:27:53,155
So, if you do a get to the checkJWTToken by

365
00:27:53,155 --> 00:27:58,700
including the token into the authorization header,

366
00:27:58,700 --> 00:28:02,490
then this call will return a true or false

367
00:28:02,490 --> 00:28:06,535
to indicate to you whether the JSON Web Token is still valid or not.

368
00:28:06,535 --> 00:28:10,930
If it is not valid, then the client-side can initiate another login for

369
00:28:10,930 --> 00:28:15,945
the user to obtain a new JSON Web Token if required.

370
00:28:15,945 --> 00:28:17,285
So, to do this,

371
00:28:17,285 --> 00:28:27,109
we'll say cors.corsWithOptions and req,

372
00:28:27,109 --> 00:28:31,385
res here as expected.

373
00:28:31,385 --> 00:28:35,670
In here, we'll say

374
00:28:39,820 --> 00:28:49,360
passport authenticate jwt

375
00:28:49,360 --> 00:28:57,150
and session: false,

376
00:29:00,020 --> 00:29:07,270
and this would return err, user, info.

377
00:29:09,020 --> 00:29:13,770
So, recall how we use the passport authenticate earlier.

378
00:29:13,770 --> 00:29:17,195
So, we call the JWT with session false here.

379
00:29:17,195 --> 00:29:21,745
So, earlier here, we say passport authenticate local.

380
00:29:21,745 --> 00:29:23,535
So, this is for the local authentication.

381
00:29:23,535 --> 00:29:27,330
So, this is for the JSON Web Token authentication.

382
00:29:27,330 --> 00:29:29,430
So, when we call that,

383
00:29:29,430 --> 00:29:33,435
then since that is going to verify the JSON Web Token, so we'll say,

384
00:29:33,435 --> 00:29:40,335
if err return next err,

385
00:29:40,335 --> 00:29:44,895
and then let the express error handler take care of that situation.

386
00:29:44,895 --> 00:29:50,469
Then, we'll say, if not user,

387
00:29:53,330 --> 00:30:00,330
if the user doesn't exist, then similarly else.

388
00:30:00,330 --> 00:30:03,510
So, which means that if the user object was

389
00:30:03,510 --> 00:30:07,810
found from the JSON Web Token and then loaded onto the req.user,

390
00:30:07,810 --> 00:30:11,400
then that means that the user is a valid user,

391
00:30:11,400 --> 00:30:13,485
and so can be allowed to proceed further.

392
00:30:13,485 --> 00:30:20,330
Otherwise, we're going to say that the user doesn't exist.

393
00:30:20,330 --> 00:30:24,995
So, we need to inform that the JSON Web Token has expired.

394
00:30:24,995 --> 00:30:26,180
So, at this point,

395
00:30:26,180 --> 00:30:29,090
we'll send a res with

396
00:30:29,090 --> 00:30:36,545
a status code of 401.

397
00:30:36,545 --> 00:30:47,130
So, unauthorized, setHeader, Content-Type,

398
00:30:49,900 --> 00:30:56,280
application/json, and then we'll return res.

399
00:30:58,680 --> 00:31:13,750
Res.json will say status JWT

400
00:31:13,750 --> 00:31:17,090
invalid and then,

401
00:31:17,730 --> 00:31:23,690
we'll return a flag called success falls and then,

402
00:31:23,880 --> 00:31:29,080
we'll return the info that we obtain if the user is

403
00:31:29,080 --> 00:31:34,460
not authenticated as the error at this point.

404
00:31:36,420 --> 00:31:40,480
Otherwise, that means that we reached this point,

405
00:31:40,480 --> 00:31:43,220
then the user is a valid user.

406
00:31:43,220 --> 00:31:44,850
So, in this case,

407
00:31:44,850 --> 00:31:47,230
let me just copy that code here,

408
00:31:47,230 --> 00:31:54,070
we'll be sending a status code of 200 and then the res.json,

409
00:31:54,070 --> 00:32:02,720
will send JWT valid and successful being true.

410
00:32:02,940 --> 00:32:09,820
The third part, we will send the user's information.

411
00:32:09,820 --> 00:32:16,000
So that way, when this endpoint is called with the get method,

412
00:32:16,000 --> 00:32:19,170
then this will verify whether the token is valid or not.

413
00:32:19,170 --> 00:32:20,220
If the token is valid,

414
00:32:20,220 --> 00:32:24,020
then you will receive this reply and from the success flag in the reply,

415
00:32:24,020 --> 00:32:27,770
you can check to see whether the jsonwebtoken is valid or not.

416
00:32:27,770 --> 00:32:32,155
This is useful on the client side.

417
00:32:32,155 --> 00:32:37,825
Now, this passport authenticate here will have to be supplied

418
00:32:37,825 --> 00:32:43,790
with req and res as the two parameters here.

419
00:32:43,790 --> 00:32:47,630
So, that's how we call the passport authenticate.

420
00:32:47,630 --> 00:32:49,355
So, notice that whenever you call

421
00:32:49,355 --> 00:32:52,840
passport authenticate and expect this callback function in here,

422
00:32:52,840 --> 00:33:01,825
you need to append to this point req.res to the passport authenticate at the back here.

423
00:33:01,825 --> 00:33:03,890
In our rest API server,

424
00:33:03,890 --> 00:33:07,490
we had implemented our comments in such a way that the comments

425
00:33:07,490 --> 00:33:12,245
formed sub-documents inside the dishe's document,

426
00:33:12,245 --> 00:33:16,540
so they buy every dish enclosed its own set of comments.

427
00:33:16,540 --> 00:33:19,520
But the way we implemented our React client is

428
00:33:19,520 --> 00:33:22,965
such that the comments are kept independent of the dishes,

429
00:33:22,965 --> 00:33:27,680
and the comments themselves carried the corresponding dish ID.

430
00:33:27,680 --> 00:33:30,400
Now, these are two different ways of

431
00:33:30,400 --> 00:33:34,445
implementing the server-side as well as the client side.

432
00:33:34,445 --> 00:33:39,685
In the Angular application that we are implemented in our Angular specialization,

433
00:33:39,685 --> 00:33:43,470
we had used the sub-document method for

434
00:33:43,470 --> 00:33:47,560
handling comments in our Angular client application.

435
00:33:47,560 --> 00:33:50,050
So, the rest API server was

436
00:33:50,050 --> 00:33:54,090
implemented in such a way that it was more suitable for the Angular client.

437
00:33:54,090 --> 00:34:00,600
But for the React clients since we kept the comments independent of the dishes,

438
00:34:00,600 --> 00:34:03,985
and then use the dish ID inside the comment,

439
00:34:03,985 --> 00:34:09,300
so we need to restructure our rest API server,

440
00:34:09,300 --> 00:34:16,835
so it's that we have a separate comment endpoint independent of the dishes endpoint.

441
00:34:16,835 --> 00:34:22,310
So, we need to restructure our code in the server

442
00:34:22,310 --> 00:34:29,140
to introduce the /comments REST API endpoint at this stage.

443
00:34:29,140 --> 00:34:30,600
So, to do that,

444
00:34:30,600 --> 00:34:37,540
let's go ahead and implement a new model called as comment.js.

445
00:34:37,540 --> 00:34:39,260
So, going into the models,

446
00:34:39,260 --> 00:34:45,790
let me implement a new file named comments.js.

447
00:34:47,220 --> 00:34:50,015
In the comments.js file,

448
00:34:50,015 --> 00:34:56,110
we're going to move the commentSchema from the dishes.js

449
00:34:56,110 --> 00:35:02,660
file into the comments.js file and then remove it completely from the dishes.js file.

450
00:35:02,660 --> 00:35:03,900
But before we do that,

451
00:35:03,900 --> 00:35:08,770
we need to copy the mongoose and the schema from here,

452
00:35:08,770 --> 00:35:13,860
so let me just copy this from dishes.js into comment.js.

453
00:35:13,860 --> 00:35:16,590
After that, going into dishes.js,

454
00:35:16,590 --> 00:35:21,040
let me cut this commentSchema completely out from here,

455
00:35:21,040 --> 00:35:28,300
because we will be having this separately in the comments model here.

456
00:35:28,300 --> 00:35:33,070
So, let's move that into the comments model and then paste it in here.

457
00:35:33,070 --> 00:35:35,050
But of course this is not the complete one,

458
00:35:35,050 --> 00:35:37,870
we're going to be updating the commentSchema a little bit.

459
00:35:37,870 --> 00:35:39,300
But before we do that,

460
00:35:39,300 --> 00:35:43,455
go back to dishes.js file and in the dishes file,

461
00:35:43,455 --> 00:35:47,925
we will remove the comments from the dishesSchema,

462
00:35:47,925 --> 00:35:51,510
because we're going to be storing the content separately from

463
00:35:51,510 --> 00:35:55,550
the dishes in this version of our server.

464
00:35:55,550 --> 00:36:00,450
So, that's how we will update the dishes model here.

465
00:36:00,450 --> 00:36:08,180
So, we have removed the comments completely from the dishes model here.

466
00:36:08,180 --> 00:36:10,270
Going into the comments model,

467
00:36:10,270 --> 00:36:15,355
so we now see that we have the commentSchema implemented here.

468
00:36:15,355 --> 00:36:19,525
But in addition, in the commentsSchema,

469
00:36:19,525 --> 00:36:23,330
we now need to explicitly point to

470
00:36:23,330 --> 00:36:28,885
the specific dish for which this comment is the corresponding comment.

471
00:36:28,885 --> 00:36:30,700
Now, this is where

472
00:36:30,700 --> 00:36:37,435
our mongoose population and

473
00:36:37,435 --> 00:36:41,580
the way we store the object Ids comes to our rescue.

474
00:36:41,580 --> 00:36:45,860
So, we will be updating the commentSchema saying we'll have the rating,

475
00:36:45,860 --> 00:36:47,800
the comment, and author here.

476
00:36:47,800 --> 00:36:49,110
In addition to the author,

477
00:36:49,110 --> 00:36:56,080
we will introduce one more field called as the dish here which is of

478
00:36:56,080 --> 00:37:05,540
the type: mongoose.Schema types.ObjectId,

479
00:37:06,390 --> 00:37:19,870
and so this will refer to the Dish here.

480
00:37:19,870 --> 00:37:29,060
So, this would be a object reference to the dish model here,

481
00:37:29,060 --> 00:37:32,255
and so with this modification now

482
00:37:32,255 --> 00:37:36,640
our comments will contain the rating field, the comment field,

483
00:37:36,640 --> 00:37:42,355
the author which is again a reference to the corresponding user,

484
00:37:42,355 --> 00:37:47,660
and then the dish field which is a reference to the corresponding dish here.

485
00:37:47,660 --> 00:37:50,060
So, which means that we will now need to

486
00:37:50,060 --> 00:37:53,640
populate the comments with both the author and the dish field.

487
00:37:53,640 --> 00:37:55,565
Once we have completed this,

488
00:37:55,565 --> 00:38:01,585
then we will say var Comments

489
00:38:01,585 --> 00:38:09,910
mongoose.model and we will call this 'Comment',

490
00:38:09,910 --> 00:38:16,765
and then this uses the commentSchema that we have just defined here,

491
00:38:16,765 --> 00:38:21,970
and then we need to export this from here,

492
00:38:21,970 --> 00:38:25,280
the comments.model from here.

493
00:38:25,280 --> 00:38:28,395
So, now that we have introduced the comments.model,

494
00:38:28,395 --> 00:38:35,045
then we will go ahead and then introduce a new Router called as the commentRouter.

495
00:38:35,045 --> 00:38:37,060
So, to introduce the comment router,

496
00:38:37,060 --> 00:38:39,630
let's go into the routes here,

497
00:38:39,630 --> 00:38:45,990
and then create a new file named commentRouter.js.

498
00:38:47,090 --> 00:38:52,415
In the commentRouter.js, let me copy a few things

499
00:38:52,415 --> 00:38:59,890
over from the dishRouter.

500
00:38:59,890 --> 00:39:07,720
So, we will have these comments here,

501
00:39:07,720 --> 00:39:14,865
so let me copy over these things from the and also,

502
00:39:14,865 --> 00:39:21,070
while I'm at it let me just copy these also up to that point,

503
00:39:21,070 --> 00:39:24,625
and then I'll update that a little bit later.

504
00:39:24,625 --> 00:39:26,680
So, going into the commentRouter,

505
00:39:26,680 --> 00:39:28,040
we need all these parts,

506
00:39:28,040 --> 00:39:33,640
so we'll say Com, Express, bodyParser, mongoose,

507
00:39:33,640 --> 00:39:37,735
authenticate, cors, and then we will

508
00:39:37,735 --> 00:39:46,490
be importing comments from models/comments.

509
00:39:49,950 --> 00:40:00,460
Then we'll call this as the commentRouter which is an express.Router here.

510
00:40:02,060 --> 00:40:11,950
Then we'll say commentRouter use bodyParser,

511
00:40:11,950 --> 00:40:17,915
and then this would now become commentRouter route.

512
00:40:17,915 --> 00:40:22,030
Now, we need to go into the dishRouter and then

513
00:40:22,030 --> 00:40:27,200
remove all the parts that refers to the comments here.

514
00:40:27,200 --> 00:40:34,330
So, let me just cut out this part and then we will reuse these for our commentRouter.

515
00:40:34,330 --> 00:40:38,200
So, all these are no longer needed in the dishRouter.

516
00:40:38,200 --> 00:40:42,080
So, I'm going to remove all this from the dishRouter here,

517
00:40:42,080 --> 00:40:43,770
so let me cut them out,

518
00:40:43,770 --> 00:40:48,715
everything related to the comments route from the dishRouter,

519
00:40:48,715 --> 00:40:50,770
then we'll go into the commentRouter,

520
00:40:50,770 --> 00:40:54,405
and then let me go ahead and paste that into place here,

521
00:40:54,405 --> 00:40:57,100
then we will edit that here.

522
00:40:57,100 --> 00:41:02,660
Then after this, we need to export the commentRouter.

523
00:41:05,160 --> 00:41:08,205
So, will export the commentRouter for us.

524
00:41:08,205 --> 00:41:12,060
But of course, this code is not completely accurate.

525
00:41:12,060 --> 00:41:14,995
So, we need to go ahead and fix this code here.

526
00:41:14,995 --> 00:41:16,585
So, for this code,

527
00:41:16,585 --> 00:41:20,180
we now realize that this is not the dishRouter route,

528
00:41:20,180 --> 00:41:21,785
instead that should be

529
00:41:21,785 --> 00:41:27,700
the /endpoint because we're

530
00:41:27,700 --> 00:41:33,685
going to be mounting this in the /comments endpoint here.

531
00:41:33,685 --> 00:41:35,685
So, we'll say commentRouter,

532
00:41:35,685 --> 00:41:39,859
and then the options corsWithOptions (req,

533
00:41:39,859 --> 00:41:42,550
res) which remains as such there,

534
00:41:42,550 --> 00:41:48,429
and then the get cors.cors and then req.res,

535
00:41:48,429 --> 00:41:52,460
and then this one will become comments.

536
00:41:53,880 --> 00:41:58,430
FindById, req.

537
00:42:00,600 --> 00:42:05,330
So, this would be Comments.find

538
00:42:07,050 --> 00:42:17,080
and req.query here.

539
00:42:17,080 --> 00:42:20,920
So, when the comments is found,

540
00:42:20,920 --> 00:42:22,974
then, at this point,

541
00:42:22,974 --> 00:42:25,940
we will populate the author,

542
00:42:26,880 --> 00:42:30,430
already have there, populate here.

543
00:42:30,430 --> 00:42:33,380
So, I'm just going to remove this comments.author, and then,

544
00:42:33,380 --> 00:42:37,410
we'll just simply populate the author here.

545
00:42:37,410 --> 00:42:44,425
Then, this would give us comments here.

546
00:42:44,425 --> 00:42:49,310
Then, we'll say, this can be simplified significantly.

547
00:42:49,310 --> 00:42:53,835
So, the catch error is there anyway.

548
00:42:53,835 --> 00:43:00,805
So, when the comment's coming, it'll simply return.

549
00:43:00,805 --> 00:43:03,910
Sorry, that should be.

550
00:43:03,910 --> 00:43:06,525
So, if for the get,

551
00:43:06,525 --> 00:43:09,305
when we get the comments,

552
00:43:09,305 --> 00:43:13,760
Comments.find req.query,.populate author here,

553
00:43:13,760 --> 00:43:18,010
and then, we'll say,.then comments,

554
00:43:18,010 --> 00:43:21,619
and then, we'll say, res.statusCode 200,

555
00:43:21,619 --> 00:43:27,605
setHeader, and then, we'll return the comments from here,

556
00:43:27,605 --> 00:43:30,850
res.json comments from here.

557
00:43:30,850 --> 00:43:36,970
Now, I am not populating the dishes here because I don't explicitly need

558
00:43:36,970 --> 00:43:45,300
the dishes the way I use this information in my react client.

559
00:43:45,300 --> 00:43:46,840
I only need the dish ID,

560
00:43:46,840 --> 00:43:49,085
and the dish ID is already present there,

561
00:43:49,085 --> 00:43:55,310
and that is good enough for me to use this data in my react client.

562
00:43:55,310 --> 00:43:57,685
So, I'm going to leave it as such there.

563
00:43:57,685 --> 00:43:59,530
I'm only going to populate

564
00:43:59,530 --> 00:44:02,910
the author information there because we need the full author information

565
00:44:02,910 --> 00:44:08,930
whenever we render a comment item in our react client.

566
00:44:08,930 --> 00:44:12,655
So, the get will be updated like this here.

567
00:44:12,655 --> 00:44:22,015
For the post corsWithOptions,

568
00:44:22,015 --> 00:44:26,070
we'll say, authenticate.verifyUser req, res, next.

569
00:44:26,070 --> 00:44:29,540
Obviously, for a comment to be posted,

570
00:44:29,540 --> 00:44:38,315
you need the author to be a valid logged in user.

571
00:44:38,315 --> 00:44:42,910
Only then, you will allow the user to post a comment.

572
00:44:42,910 --> 00:44:49,020
Then, the comment itself comes in the body of the incoming request message.

573
00:44:49,020 --> 00:44:51,810
So, first, we'll check the body

574
00:44:51,810 --> 00:44:58,865
to make sure that the comment is included in the body here.

575
00:44:58,865 --> 00:45:03,730
So, here, I'm going to remove all these parts, and then,

576
00:45:03,730 --> 00:45:06,100
simplify it further, and then,

577
00:45:06,100 --> 00:45:09,430
we'll implement this correctly there.

578
00:45:09,430 --> 00:45:17,755
So, right at this point, we'll say,

579
00:45:17,755 --> 00:45:27,465
if req.body not equal to null,

580
00:45:27,465 --> 00:45:35,030
so which means that there is a comment that is enclosed inside the body.

581
00:45:37,380 --> 00:45:45,025
So, let me cut this and move this into the if part here,

582
00:45:45,025 --> 00:45:47,155
and then, we'll edit that here.

583
00:45:47,155 --> 00:45:52,245
So, if the body doesn't exist,

584
00:45:52,245 --> 00:45:56,140
then we will cause an error.

585
00:45:56,140 --> 00:46:01,220
So, we'll say, err new Error,

586
00:46:01,500 --> 00:46:08,965
Comment not found in request body.

587
00:46:08,965 --> 00:46:12,440
So, we'll raise this error here.

588
00:46:12,450 --> 00:46:16,425
Error status is 404.

589
00:46:16,425 --> 00:46:20,385
Then, we'll say, return next error.

590
00:46:20,385 --> 00:46:26,560
So, let's handle the error part here if the body

591
00:46:26,560 --> 00:46:33,280
doesn't contain the appropriate comment information.

592
00:46:33,280 --> 00:46:35,450
If it contains, then, of course,

593
00:46:35,450 --> 00:46:38,170
what we will do next is,

594
00:46:38,170 --> 00:46:48,310
we'll say, req.body.author is req.user._id.

595
00:46:50,420 --> 00:46:55,610
The reason why we're doing this is that we recall that if it

596
00:46:55,610 --> 00:46:59,950
is a registered user and the user has logged in,

597
00:46:59,950 --> 00:47:03,050
then the req.user will contain the user information.

598
00:47:03,050 --> 00:47:07,260
So, I only need the ID of the currently logged in user.

599
00:47:07,260 --> 00:47:10,310
So, we'll say, req.user._id, and then,

600
00:47:10,310 --> 00:47:14,645
we'll set the req.body.author to req.user._id.

601
00:47:14,645 --> 00:47:20,070
Now, the verify user will automatically ensure that if you land at this point,

602
00:47:20,070 --> 00:47:25,710
then you would obviously have a user that has logged in correctly.

603
00:47:25,710 --> 00:47:28,605
Otherwise, that would have already caused the problem there.

604
00:47:28,605 --> 00:47:30,260
So, when you reach at this point,

605
00:47:30,260 --> 00:47:37,660
you would have a valid user that has already logged in to the system in there.

606
00:47:37,660 --> 00:47:43,460
So, this is where you would be able to now.

607
00:47:43,460 --> 00:47:46,040
So, what we are doing is that the author field,

608
00:47:46,040 --> 00:47:50,625
we are explicitly setting it into the user's ID here so that

609
00:47:50,625 --> 00:47:57,490
the req.body contains the remaining parts of the comment.

610
00:47:57,490 --> 00:48:01,315
So, as you realize, the comment contains the rating,

611
00:48:01,315 --> 00:48:04,540
the comment itself, and the author, and the dish fields.

612
00:48:04,540 --> 00:48:11,510
So, the remaining parts should have been filled by the user.

613
00:48:11,510 --> 00:48:14,730
The rating, the comment,

614
00:48:14,730 --> 00:48:17,775
and the dish information should already be filled

615
00:48:17,775 --> 00:48:20,840
into the body of the incoming request message.

616
00:48:20,840 --> 00:48:23,460
The author part is left unfilled there,

617
00:48:23,460 --> 00:48:28,380
which we will explicitly insert at this point into the body here.

618
00:48:28,380 --> 00:48:32,515
So, now, the req.body will contain the entire comment information.

619
00:48:32,515 --> 00:48:34,440
So, at this point,

620
00:48:34,440 --> 00:48:43,400
instead of doing this, we'll say, Comments.create.

621
00:48:44,550 --> 00:48:49,940
Using the req.body, we'll create the comments here.

622
00:48:50,010 --> 00:48:53,304
Then, this will return

623
00:48:53,304 --> 00:48:58,735
the comment corresponding to the comment that we have just inserted here.

624
00:48:58,735 --> 00:49:00,755
Now, once the comment has returned,

625
00:49:00,755 --> 00:49:07,050
then we should do Comments.findById.

626
00:49:07,050 --> 00:49:09,680
Now, the reason we need to do this is because we need

627
00:49:09,680 --> 00:49:13,070
to populate the author information here.

628
00:49:13,780 --> 00:49:18,144
So, we'll say, findById comments._id,

629
00:49:18,144 --> 00:49:26,155
and then, we'll populate the author information into the comment itself.

630
00:49:26,155 --> 00:49:34,610
Then, we'll say, then comment.

631
00:49:36,570 --> 00:49:41,115
Now, obviously, here, you would find that the comment will

632
00:49:41,115 --> 00:49:44,880
exist because we just inserted that comment into place there.

633
00:49:44,880 --> 00:49:54,470
So, here, we will simply return, res.statusCode is 200,

634
00:49:54,900 --> 00:50:10,040
res.setHeader is Content-Type, application/json.

635
00:50:14,610 --> 00:50:18,430
The comment itself will say, res.json, and then,

636
00:50:18,430 --> 00:50:21,745
return the comment at this point.

637
00:50:21,745 --> 00:50:26,255
So, this is the way we will handle the insertion of

638
00:50:26,255 --> 00:50:30,805
a new comment into our client side here.

639
00:50:30,805 --> 00:50:33,925
For the put, as you realize,

640
00:50:33,925 --> 00:50:38,360
you won't be able to do a put on the /comments/ end points.

641
00:50:38,360 --> 00:50:47,610
So, we'll say, PUT operation not supported on /comments/ end point.

642
00:50:52,050 --> 00:50:56,180
That's the point. That's the message that you'll return.

643
00:50:56,180 --> 00:50:58,570
So, statusCode is 403,

644
00:50:58,570 --> 00:51:02,610
and then, PUT operation not supported on /comments/.

645
00:51:02,610 --> 00:51:05,260
Now, when we do a delete,

646
00:51:13,230 --> 00:51:22,840
let me just cut this from here, and then, we'll say,

647
00:51:30,440 --> 00:51:32,835
Comments.remove.

648
00:51:32,835 --> 00:51:37,710
written empty. So, when you do a delete on the slash comments endpoint,

649
00:51:37,710 --> 00:51:40,990
you will remove all the comments from your system.

650
00:51:40,990 --> 00:51:43,680
So, this is a very dangerous operation, and so,

651
00:51:43,680 --> 00:51:48,990
you should not be doing this normally.

652
00:51:48,990 --> 00:51:53,860
So, we'll only allow the admin to perform such an operation.

653
00:51:53,860 --> 00:51:59,410
So, we'll remove all the comments from there.

654
00:51:59,410 --> 00:52:01,940
So, when you get the response,

655
00:52:01,940 --> 00:52:07,700
then we'll say res.statusCode 200.

656
00:52:07,700 --> 00:52:11,080
So, let me just copy these parts here,

657
00:52:12,090 --> 00:52:18,130
and then come and paste it in here.

658
00:52:18,130 --> 00:52:21,330
So, we'll say, comments.remove.

659
00:52:21,330 --> 00:52:30,480
Then response res.statusCode 200 application json and then res.json(response) here.

660
00:52:30,480 --> 00:52:33,100
So, that's how we handle the deletion.

661
00:52:33,100 --> 00:52:37,280
Delete operation on the slash comments endpoint.

662
00:52:37,280 --> 00:52:43,135
Now, the next route is the comment router.

663
00:52:43,135 --> 00:52:49,490
So, here we'll say commentRouter.route and

664
00:52:49,490 --> 00:52:56,820
the end point here would be the slash commentId.

665
00:53:01,190 --> 00:53:05,580
So, here the options will remain as such.

666
00:53:05,580 --> 00:53:09,760
Then for the get on the current router,

667
00:53:09,760 --> 00:53:20,455
for the get we'll say, Comments.findbyID( req.params.

668
00:53:20,455 --> 00:53:25,040
This would be commentId.

669
00:53:25,380 --> 00:53:31,029
So, once we find the specific comment,

670
00:53:31,029 --> 00:53:37,525
then we will populate just the author from there.

671
00:53:37,525 --> 00:53:39,985
Then once you populate the author,

672
00:53:39,985 --> 00:53:45,830
then we'll say, then comment.

673
00:53:47,880 --> 00:53:51,310
Now, all this part is unnecessary here,

674
00:53:51,310 --> 00:53:54,440
so I'm just going to delete the part.

675
00:53:54,480 --> 00:54:00,985
This is also not the appropriate thing here.

676
00:54:00,985 --> 00:54:04,540
So, let me rename code.

677
00:54:04,540 --> 00:54:08,990
So, we'll say for the get Comments.findById,

678
00:54:11,550 --> 00:54:15,385
then populate the author,

679
00:54:15,385 --> 00:54:20,365
then comment, res.statusCode is 200, setHeader.

680
00:54:20,365 --> 00:54:22,435
Then the rest are json.

681
00:54:22,435 --> 00:54:29,960
We will be simply returning the comments here.

682
00:54:39,240 --> 00:54:46,750
So, we'll be returning the comment at this point, res.json(comment).

683
00:54:46,750 --> 00:54:49,340
You'll find the specific comment,

684
00:54:49,340 --> 00:54:52,415
and then return that comment for the post.

685
00:54:52,415 --> 00:54:55,185
For the post-operation, as you realize,

686
00:54:55,185 --> 00:54:56,900
the post-operation is not

687
00:54:56,900 --> 00:55:06,740
allowed on comments commentId.

688
00:55:10,080 --> 00:55:13,805
So, that's the message that we'll send,

689
00:55:13,805 --> 00:55:19,110
POST operation not supported on comments slash commentId.

690
00:55:19,110 --> 00:55:23,640
So, that's the message we'll say for the put.

691
00:55:23,640 --> 00:55:33,730
Now, for the put, we'll say Comments.find where Id(req.params.commentId).

692
00:55:34,890 --> 00:55:39,230
So, we'll find the comment there,

693
00:55:40,890 --> 00:55:48,070
and there comment, so for the put.

694
00:55:48,070 --> 00:55:50,805
So, we'll find the comment there,

695
00:55:50,805 --> 00:55:53,400
and then we'll say for the comments.

696
00:55:53,400 --> 00:55:55,305
So, if we find the comment,

697
00:55:55,305 --> 00:56:07,080
if the comment is not null,

698
00:56:07,080 --> 00:56:19,455
then we'll also check if comment.author.

699
00:56:19,455 --> 00:56:32,625
If not, comment.arthur equals(req.user._id).

700
00:56:32,625 --> 00:56:38,095
So, we are cross-checking to make sure that

701
00:56:38,095 --> 00:56:43,755
the comments.author is the same as the current user.

702
00:56:43,755 --> 00:56:50,950
Only the current user who is logged in- if the user is the same as the comments author,

703
00:56:50,950 --> 00:56:53,760
then the user will be allowed to update.

704
00:56:53,760 --> 00:56:57,190
So, that's the first thing that we will check.

705
00:56:57,190 --> 00:57:01,900
So, comments, then comments.author.equal to rec.user._id.

706
00:57:01,900 --> 00:57:07,860
If not, then you will say you are not authorized to update this comment.

707
00:57:07,860 --> 00:57:10,859
As you see the.403,

708
00:57:10,859 --> 00:57:13,090
and then return next error here.

709
00:57:13,090 --> 00:57:16,705
So, we'll create the error there.

710
00:57:16,705 --> 00:57:21,800
Then after this, then we'll say

711
00:57:29,910 --> 00:57:36,860
req.body.author, req.user._id.

712
00:57:40,010 --> 00:57:42,215
That's important.

713
00:57:42,215 --> 00:57:45,580
Now, these two are not necessary here,

714
00:57:45,580 --> 00:57:51,385
because we are directly saving the comment.

715
00:57:51,385 --> 00:58:05,980
Then pills, we'll say comments.findByIdAndUpdate,

716
00:58:05,980 --> 00:58:14,965
and req.params.commentId.

717
00:58:14,965 --> 00:58:18,395
So, we'll find that specific comment,

718
00:58:18,395 --> 00:58:21,925
because we have already been supplied the comment ID.

719
00:58:21,925 --> 00:58:27,205
So, we'll do comments findById req.params.commentId.

720
00:58:27,205 --> 00:58:30,260
Then we'll say then(comment).

721
00:58:32,730 --> 00:58:38,705
When you supply the req.params.commentId,

722
00:58:38,705 --> 00:58:42,275
we'll have to explicitly supply the second parameter,

723
00:58:42,275 --> 00:58:45,825
which is what we want to change.

724
00:58:45,825 --> 00:58:52,285
So, we'll say $set: req.body.

725
00:58:52,285 --> 00:58:54,970
So, the second parameter, essentially,

726
00:58:54,970 --> 00:58:58,740
tells you which part you are changing.

727
00:58:58,740 --> 00:59:03,710
Now, since we have been supplied the body containing the updated comment,

728
00:59:03,710 --> 00:59:09,140
we're just going to update the entire comment itself.

729
00:59:09,510 --> 00:59:18,205
Then the other part we'll ask for is new: true.

730
00:59:18,205 --> 00:59:23,240
So, this will ensure that the updated comment will be returned in

731
00:59:23,240 --> 00:59:29,815
the den of this call to the Comments.FindByIdAndUpdate.

732
00:59:29,815 --> 00:59:32,565
So, we'll say then comments.

733
00:59:32,565 --> 00:59:35,214
When that comment is returned,

734
00:59:35,214 --> 00:59:38,440
then we'll say Comments.findById(comment._id).

735
00:59:46,200 --> 00:59:51,460
Then populate the author there.

736
00:59:51,460 --> 00:59:53,785
We'll populate the author there,

737
00:59:53,785 --> 00:59:58,490
and then we'll say then comment.

738
00:59:58,700 --> 01:00:09,680
So, you see that we'll obtain the comment and then return the comment at this point.

739
01:00:09,680 --> 01:00:13,095
So, that's how we will be updating the comment.

740
01:00:13,095 --> 01:00:17,395
So, this is the situation where the comment is not null.

741
01:00:17,395 --> 01:00:20,625
So, this if statement for the comment is not null.

742
01:00:20,625 --> 01:00:23,785
So, the else if part,

743
01:00:23,785 --> 01:00:29,020
now this is not applicable,

744
01:00:29,020 --> 01:00:33,325
so we'll say else, error.

745
01:00:33,325 --> 01:00:35,470
The error in this case.

746
01:00:35,470 --> 01:00:37,825
So, if the comment is null,

747
01:00:37,825 --> 01:00:40,850
that means that we did not find the comment in there,

748
01:00:40,850 --> 01:00:43,650
so you cannot modify a non-existent comment.

749
01:00:43,650 --> 01:00:44,805
So we'll say err,

750
01:00:44,805 --> 01:00:54,700
new Error comment req.params.commentId not found and then we'll return the error.

751
01:00:54,700 --> 01:01:01,255
So, that's how we will handle the put part of our comment here,

752
01:01:01,255 --> 01:01:04,099
and then finally the delete.

753
01:01:06,120 --> 01:01:11,130
For the delete, again we'll have to first find

754
01:01:11,130 --> 01:01:12,900
Comments.findById(req.params.commentId)

755
01:01:12,900 --> 01:01:25,720
and then comment.

756
01:01:25,720 --> 01:01:28,150
So, we'll look for the comment.

757
01:01:28,150 --> 01:01:34,160
So, we'll first check if comment is not equal to null.

758
01:01:36,180 --> 01:01:39,955
That's important to check here.

759
01:01:39,955 --> 01:01:50,990
Then, the next part we will check for is if the comment.author equals req.user._id.

760
01:01:58,830 --> 01:02:03,400
We make sure that this user that is trying to delete

761
01:02:03,400 --> 01:02:08,060
this comment is exactly the same user that inserted the comment in the first place.

762
01:02:08,060 --> 01:02:10,750
If not, so if this is the situation,

763
01:02:10,750 --> 01:02:13,920
then you will see 'You are not authorized to delete this comment!'

764
01:02:13,920 --> 01:02:16,365
And then return the status there.

765
01:02:16,365 --> 01:02:20,920
Then down below here,

766
01:02:20,920 --> 01:02:41,310
we'll say Comments.findByIdAndRemove here.

767
01:02:41,310 --> 01:02:48,750
So, we'll say comments.findByIdAndRemove(req.params.commentId),

768
01:02:48,750 --> 01:02:54,035
then we'll get some response from the comment.

769
01:02:54,035 --> 01:02:55,630
So, at this point,

770
01:02:55,630 --> 01:02:59,830
we'll simply say, res.statusCode.

771
01:02:59,830 --> 01:03:05,365
So we'll say Comments.findByIdAndRemove then response.

772
01:03:05,365 --> 01:03:07,210
If it is correctly removed,

773
01:03:07,210 --> 01:03:10,915
we'll say 200 and then res.json

774
01:03:10,915 --> 01:03:17,260
response here and we will also catch the error at this point.

775
01:03:17,260 --> 01:03:25,195
So, let me just copy that here and then we'll include the catch of the err at this point.

776
01:03:25,195 --> 01:03:28,895
So, that's the first thing that we'll check.

777
01:03:28,895 --> 01:03:33,500
We'll ensure that the comment is not equal to null.

778
01:03:33,630 --> 01:03:38,360
Otherwise, so this is the else part.

779
01:03:39,810 --> 01:03:44,170
So, this is the else part of the if else error

780
01:03:44,170 --> 01:03:48,040
new comment req.params.commentId not found and then

781
01:03:48,040 --> 01:03:56,220
404 and send the else part for us and then the then part will handle appropriately.

782
01:03:56,220 --> 01:04:01,460
So, this is the changes that we make for the comment router here.

783
01:04:01,460 --> 01:04:05,025
So, we are handling the get put post and delete for

784
01:04:05,025 --> 01:04:10,330
the slash comments and point slash comments slash commentId impact.

785
01:04:10,330 --> 01:04:12,495
So once we have completed this,

786
01:04:12,495 --> 01:04:17,500
then we need to include this into the app.js file.

787
01:04:17,500 --> 01:04:27,345
So, we'll go into the app.js file and then we'll say

788
01:04:27,345 --> 01:04:30,070
var commentRouter

789
01:04:31,130 --> 01:04:42,280
require routes/commentRouter.

790
01:04:42,280 --> 01:04:45,960
So, we have the comment router here and then we'll go

791
01:04:45,960 --> 01:04:49,390
down into the app.js file down below here and

792
01:04:49,390 --> 01:04:54,610
then we will say app.use

793
01:04:55,040 --> 01:05:04,695
slash comments, commentRouter here.

794
01:05:04,695 --> 01:05:07,365
That's it. So now,

795
01:05:07,365 --> 01:05:09,390
my comment router is ready.

796
01:05:09,390 --> 01:05:12,935
So, let's go ahead and save all the changes.

797
01:05:12,935 --> 01:05:19,020
Then our server is now updated in

798
01:05:19,020 --> 01:05:24,420
order to handle all the requests from our React clients here.

799
01:05:24,420 --> 01:05:27,800
Now, if you want to do the alternative way, that is,

800
01:05:27,800 --> 01:05:34,120
you have your comments as sub-documents of your dish and then you want to handle that,

801
01:05:34,120 --> 01:05:37,680
then you will need to update the React client to be able

802
01:05:37,680 --> 01:05:42,185
to use the comments from within each dish appropriately.

803
01:05:42,185 --> 01:05:44,830
That will be left as an exercise for you.

804
01:05:44,830 --> 01:05:48,920
Think about how you would design your react client such that it

805
01:05:48,920 --> 01:05:53,465
works very well with the earlier version of

806
01:05:53,465 --> 01:06:03,735
the server which had the comments as sub-documents of your dishes themselves.

807
01:06:03,735 --> 01:06:07,065
Now, that'll be an interesting way of implementing it.

808
01:06:07,065 --> 01:06:10,480
Of course, it's a bit more complicated than the way we

809
01:06:10,480 --> 01:06:14,965
implemented the React client where we kept the comments independent of

810
01:06:14,965 --> 01:06:20,840
the dishes but then the additional work is then the responsibility

811
01:06:20,840 --> 01:06:22,910
of the client side because you need to select

812
01:06:22,910 --> 01:06:26,765
the appropriate comments when you're showing a specific dish.

813
01:06:26,765 --> 01:06:30,370
You need to select the comments from all the comments here.

814
01:06:30,370 --> 01:06:35,170
So, that's one additional work that our React client does because of

815
01:06:35,170 --> 01:06:40,680
the fact that we separated the comments from the dishes themselves.

816
01:06:40,680 --> 01:06:46,165
Similarly, if you can redesign your angular client to be able to

817
01:06:46,165 --> 01:06:51,775
deal with the situation where the comments are kept independent of your dishes.

818
01:06:51,775 --> 01:06:56,020
Now, so these are all exercises that you can do in order to see how you can

819
01:06:56,020 --> 01:07:01,210
extend your client applications to handle any kind of server,

820
01:07:01,210 --> 01:07:04,430
the two different kinds of servers there.

821
01:07:04,860 --> 01:07:11,480
So, with this, we complete the update to our server here.

822
01:07:11,480 --> 01:07:15,040
So, with this, we have updated everything on the server side.

823
01:07:15,040 --> 01:07:17,890
So, let's save all the changes on the server side.

824
01:07:17,890 --> 01:07:26,755
So now, our server is all ready to handle the incoming requests from our React client.

825
01:07:26,755 --> 01:07:29,340
With this, we complete this exercise.

826
01:07:29,340 --> 01:07:33,300
In this exercise, we have now prepared our express server

827
01:07:33,300 --> 01:07:38,985
to handle incoming requests from our React client.

828
01:07:38,985 --> 01:07:43,190
In the next exercise, we're going to look at react client in more detail to

829
01:07:43,190 --> 01:07:48,000
understand how it is communicating with this extra server.

830
01:07:48,000 --> 01:07:50,640
This is a good time for you to do

831
01:07:50,640 --> 01:07:55,880
a git coverage with the message integrating client and server.