1
00:00:02,430 --> 00:00:03,640
Now, how can we clean up

2
00:00:03,640 --> 00:00:06,310
the navigation bar items here?

3
00:00:06,310 --> 00:00:09,670
Theoretically, it's quite straightforward.

4
00:00:09,670 --> 00:00:12,550
We have our header EJS file.

5
00:00:12,550 --> 00:00:15,850
And in there we can now render these items conditionally

6
00:00:15,850 --> 00:00:17,870
with help of EJS.

7
00:00:17,870 --> 00:00:21,230
The problem just is that the header EJS file

8
00:00:21,230 --> 00:00:24,310
is included in a bunch of templates.

9
00:00:24,310 --> 00:00:26,570
And for all those templates,

10
00:00:26,570 --> 00:00:30,480
we in the end have to forward information about the user,

11
00:00:30,480 --> 00:00:32,560
wherever he or she is logged in,

12
00:00:32,560 --> 00:00:35,250
and whether he or she should be able to visit

13
00:00:35,250 --> 00:00:37,100
the admin page.

14
00:00:37,100 --> 00:00:39,540
And that can become pretty annoying

15
00:00:39,540 --> 00:00:41,310
to do this in every route

16
00:00:41,310 --> 00:00:44,740
and forward this to every template so that in every

17
00:00:44,740 --> 00:00:48,680
template we can forward this information to the header

18
00:00:48,680 --> 00:00:52,170
that would be super annoying and a lot of copy and pasting,

19
00:00:52,170 --> 00:00:54,243
and it would be pretty error prone.

20
00:00:55,360 --> 00:00:58,170
Thankfully express JS has an easier approach,

21
00:00:58,170 --> 00:00:59,830
which we can use

22
00:00:59,830 --> 00:01:04,319
in App.js, where we have all these general middle wares

23
00:01:04,319 --> 00:01:06,210
that we can use everywhere.

24
00:01:06,210 --> 00:01:11,080
We can also write our own middleware that sets up some data

25
00:01:11,080 --> 00:01:15,080
that will be exposed to all templates automatically

26
00:01:15,080 --> 00:01:17,500
because it's such a common use case

27
00:01:17,500 --> 00:01:19,760
that you have data that should be available

28
00:01:19,760 --> 00:01:21,750
to all templates.

29
00:01:21,750 --> 00:01:25,923
All we have to do here after initializing our session here,

30
00:01:26,860 --> 00:01:30,910
we add app use and add our own function here.

31
00:01:30,910 --> 00:01:34,310
So we write our own middleware and the middleware

32
00:01:34,310 --> 00:01:37,910
just looks like this basic function we saw before

33
00:01:37,910 --> 00:01:39,710
in this course a couple of times

34
00:01:39,710 --> 00:01:42,490
where we get a request, a response,

35
00:01:42,490 --> 00:01:45,700
and then also this special, next thing,

36
00:01:45,700 --> 00:01:47,840
which we will actually use now.

37
00:01:47,840 --> 00:01:51,070
So we have to accept this as a parameter value here

38
00:01:51,070 --> 00:01:51,903
as well.

39
00:01:53,130 --> 00:01:54,560
Now in here,

40
00:01:54,560 --> 00:01:57,670
we can find out if a user is authenticated

41
00:01:57,670 --> 00:02:02,670
by reaching out to request session is authenticated

42
00:02:02,850 --> 00:02:04,330
that's this extra flag,

43
00:02:04,330 --> 00:02:06,793
which we are setting when we log a user in.

44
00:02:07,870 --> 00:02:12,520
And I also wanna find out if a user is an admin or not

45
00:02:12,520 --> 00:02:14,620
for this, I'll use my DB helper,

46
00:02:14,620 --> 00:02:17,003
which is already being required here.

47
00:02:17,970 --> 00:02:21,310
And I will turn this into an async function

48
00:02:21,310 --> 00:02:23,780
so that we can use a single weight

49
00:02:23,780 --> 00:02:27,710
and I can call, get DB to get access to my users collection

50
00:02:27,710 --> 00:02:29,803
and find one user.

51
00:02:30,920 --> 00:02:33,240
Now I need to know which user and therefore,

52
00:02:33,240 --> 00:02:36,480
I will also extract my user from my session

53
00:02:36,480 --> 00:02:39,320
just as we did it before in other parts

54
00:02:39,320 --> 00:02:41,420
of this website here.

55
00:02:41,420 --> 00:02:43,180
So I'll get req session user,

56
00:02:43,180 --> 00:02:45,283
and this might or might not be set.

57
00:02:47,150 --> 00:02:50,130
And then here a look for the user where ID

58
00:02:50,130 --> 00:02:52,513
is equal to user.id.

59
00:02:53,840 --> 00:02:56,700
That's another piece of data we're storing in a session

60
00:02:56,700 --> 00:02:59,620
and we used all of that before already.

61
00:02:59,620 --> 00:03:04,620
Now we can await this to get the user from the database

62
00:03:05,910 --> 00:03:09,150
since I have a name clash, now I'll name this user doc,

63
00:03:09,150 --> 00:03:11,253
because I have user here already.

64
00:03:12,560 --> 00:03:15,860
And I now therefore can extract the isAdmin feature

65
00:03:15,860 --> 00:03:18,160
from a user doc isAdmin.

66
00:03:18,160 --> 00:03:20,950
And this also is either on the find or false,

67
00:03:20,950 --> 00:03:22,473
or it might be true.

68
00:03:24,100 --> 00:03:27,180
Now of course, looking for a user only makes sense

69
00:03:27,180 --> 00:03:28,490
if we have one.

70
00:03:28,490 --> 00:03:31,910
So if we are not able to extract the user from the session,

71
00:03:31,910 --> 00:03:35,410
I don't wanna execute this code down there.

72
00:03:35,410 --> 00:03:38,430
So here I'll first of all, check, if not user,

73
00:03:38,430 --> 00:03:43,430
if this is faulty, or if we somehow have a user, but is off,

74
00:03:43,780 --> 00:03:45,670
is false,

75
00:03:45,670 --> 00:03:47,760
then we also know that the users certainly

76
00:03:47,760 --> 00:03:49,110
won't be authenticated.

77
00:03:49,110 --> 00:03:50,020
And in this case,

78
00:03:50,020 --> 00:03:53,820
I wanna return here so that this code doesn't execute

79
00:03:53,820 --> 00:03:57,540
and we now have to execute this next thing here,

80
00:03:57,540 --> 00:04:00,373
this next parameter as a function.

81
00:04:01,770 --> 00:04:05,110
And what this does is it simply tells express

82
00:04:05,110 --> 00:04:07,730
that this request for which this middleware

83
00:04:07,730 --> 00:04:09,510
is being executed here

84
00:04:09,510 --> 00:04:14,140
should be forwarded to the next middleware or route in line

85
00:04:15,360 --> 00:04:17,839
because this here, this middleware function,

86
00:04:17,839 --> 00:04:22,840
which we are writing will run for every incoming request,

87
00:04:22,900 --> 00:04:26,500
but it should only do some things with that request

88
00:04:26,500 --> 00:04:30,830
and then move on to the next middleware or route in line.

89
00:04:30,830 --> 00:04:33,710
And by calling next, we signal that we're done

90
00:04:33,710 --> 00:04:36,820
and that the request is now allowed to move on

91
00:04:36,820 --> 00:04:38,280
to the next middleware,

92
00:04:38,280 --> 00:04:41,800
which is this next middleware registered below in this case,

93
00:04:41,800 --> 00:04:43,520
my demo routes.

94
00:04:43,520 --> 00:04:47,660
So now this request we'll move on to the demo routes

95
00:04:47,660 --> 00:04:50,590
and it will move on if we're not authenticated.

96
00:04:50,590 --> 00:04:52,790
Of course, I also wanna move on here at the end

97
00:04:52,790 --> 00:04:54,470
if we are authenticated.

98
00:04:54,470 --> 00:04:57,123
So I should also to call next here,

99
00:04:58,120 --> 00:05:00,760
but I wanted to do it here as well to make sure

100
00:05:00,760 --> 00:05:03,090
that this code doesn't even execute,

101
00:05:03,090 --> 00:05:04,543
if we don't have a user.

102
00:05:05,740 --> 00:05:08,030
Now that alone, isn't too useful though.

103
00:05:08,030 --> 00:05:11,063
Now we're just repeating things we did before already,

104
00:05:12,020 --> 00:05:16,090
but now we can use a special express feature to store

105
00:05:16,090 --> 00:05:19,687
the information that we gathered here like isAuth

106
00:05:19,687 --> 00:05:23,200
and isAdmin in a certain place,

107
00:05:23,200 --> 00:05:26,120
which we can access from all our templates

108
00:05:26,120 --> 00:05:28,950
without explicitly passing the data to them

109
00:05:28,950 --> 00:05:32,740
and in all other parts in all our middle wares

110
00:05:32,740 --> 00:05:36,490
that come after this middleware here as well.

111
00:05:36,490 --> 00:05:40,420
And that's the res dot locals field.

112
00:05:40,420 --> 00:05:45,310
So on the response express has this locals field

113
00:05:45,310 --> 00:05:50,140
and locals allows you to set some global values,

114
00:05:50,140 --> 00:05:52,410
any values of your choice

115
00:05:52,410 --> 00:05:54,810
that will it be available throughout

116
00:05:54,810 --> 00:05:57,560
this entire request response cycle,

117
00:05:57,560 --> 00:06:00,260
but only for this request response cycle.

118
00:06:00,260 --> 00:06:03,910
A new request will not have any of that data,

119
00:06:03,910 --> 00:06:07,070
and we don't want to have that data anywhere else,

120
00:06:07,070 --> 00:06:09,510
but we wanna store it for this request,

121
00:06:09,510 --> 00:06:11,560
which we are currently handling,

122
00:06:11,560 --> 00:06:14,143
and we're storing it on this response here.

123
00:06:15,420 --> 00:06:19,390
Now, here you can add any key value pairs of your choice

124
00:06:19,390 --> 00:06:23,740
for example, isAuth and set this equal to

125
00:06:23,740 --> 00:06:25,490
isAuth in this constant

126
00:06:26,520 --> 00:06:30,620
and if we make it down there, I'll also set res locals

127
00:06:30,620 --> 00:06:34,863
isAdmin and set this equal to isAdmin here.

128
00:06:36,870 --> 00:06:39,800
And actually this can also be set to down there

129
00:06:39,800 --> 00:06:42,480
because if we don't make it past this if check,

130
00:06:42,480 --> 00:06:44,620
we know the user isn't authenticated,

131
00:06:44,620 --> 00:06:48,403
and then we don't even need to set isAuth here to anything.

132
00:06:49,530 --> 00:06:52,980
Now we have these two global variables

133
00:06:52,980 --> 00:06:55,050
and you could store more data.

134
00:06:55,050 --> 00:06:58,540
And these variables are by default available

135
00:06:58,540 --> 00:07:01,650
in all your templates, that's the big thing

136
00:07:01,650 --> 00:07:04,513
that's the big thing of this locals feature.

137
00:07:05,900 --> 00:07:09,360
We set it in our own middleware so that this code runs

138
00:07:09,360 --> 00:07:11,200
for every incoming request

139
00:07:11,200 --> 00:07:14,750
and it runs before we reached a demo routes

140
00:07:14,750 --> 00:07:18,260
so that this global data is set before we make it

141
00:07:18,260 --> 00:07:19,783
into our main routes.

142
00:07:21,600 --> 00:07:22,710
And now here,

143
00:07:22,710 --> 00:07:26,290
we can go to the header and use that information,

144
00:07:26,290 --> 00:07:28,863
for example, for this logout list item,

145
00:07:29,740 --> 00:07:34,127
and here we cannot check if locals.isAuth is truthy.

146
00:07:36,690 --> 00:07:41,690
So this locals key here with all the data we stored in it

147
00:07:41,810 --> 00:07:46,750
will be available in all templates without you passing it

148
00:07:46,750 --> 00:07:48,850
into those templates explicitly.

149
00:07:48,850 --> 00:07:53,310
And that's great for such general template, white data,

150
00:07:53,310 --> 00:07:55,390
like this isAuth state

151
00:07:56,760 --> 00:07:59,470
and here, of course, we also need to close to curly brace

152
00:07:59,470 --> 00:08:02,430
and now this list item here will only be shown

153
00:08:02,430 --> 00:08:07,430
if isAuth in this resurface locals, key and object,

154
00:08:07,560 --> 00:08:10,853
which express has built in is set to true.

155
00:08:12,280 --> 00:08:16,130
So if you save this and I reload this page here,

156
00:08:16,130 --> 00:08:19,310
I don't see it because I'm not logged in

157
00:08:19,310 --> 00:08:22,610
as you can tell if I click on admin or a profile.

158
00:08:22,610 --> 00:08:25,870
So showing log out makes no sense if I'm not logged in,

159
00:08:25,870 --> 00:08:26,993
so that works.

160
00:08:28,250 --> 00:08:31,430
Hence of course, we can also move admin and profile

161
00:08:31,430 --> 00:08:33,000
into the same if check

162
00:08:33,000 --> 00:08:36,130
because those items should also only be visible

163
00:08:36,130 --> 00:08:37,590
if we are authenticated

164
00:08:38,429 --> 00:08:41,340
and actually for admin, we can move it out of there again,

165
00:08:41,340 --> 00:08:43,970
because there we have even stricter check.

166
00:08:43,970 --> 00:08:48,540
We can check if locals.isAdmin is true

167
00:08:48,540 --> 00:08:49,520
if that's not true,

168
00:08:49,520 --> 00:08:53,600
we don't wanna show the profile link no matter

169
00:08:53,600 --> 00:08:55,750
if we are authenticated or not,

170
00:08:55,750 --> 00:08:57,773
because we need authorization for that.

171
00:09:01,990 --> 00:09:04,340
So now with that, if I save this and reload,

172
00:09:04,340 --> 00:09:07,970
these links are also gone, if I'm not logged in,

173
00:09:07,970 --> 00:09:09,933
if I do log in here,

174
00:09:10,860 --> 00:09:15,860
let's say with the non admin user, whoops,

175
00:09:18,040 --> 00:09:21,390
wrong user, this one, then I see profile,

176
00:09:21,390 --> 00:09:24,880
but not admin because this user isn't an admin.

177
00:09:24,880 --> 00:09:28,533
I also see log out and if I click it, I don't see it again.

178
00:09:29,840 --> 00:09:32,260
Now I only wanna see sign up and log in

179
00:09:32,260 --> 00:09:34,550
if we are not authenticated

180
00:09:34,550 --> 00:09:37,320
and therefore here we can run the opposite check

181
00:09:37,320 --> 00:09:40,270
and check if not isAuth

182
00:09:40,270 --> 00:09:44,700
and only in that case, I wanna show these two items.

183
00:09:44,700 --> 00:09:48,673
So also close that here like that.

184
00:09:51,260 --> 00:09:56,260
And of course it should be locals.isAuth whoops, like this.

185
00:09:56,750 --> 00:09:59,210
So local dot isAuth is what I'm checking here

186
00:09:59,210 --> 00:10:02,830
and if I'm not authenticated, I showed these items.

187
00:10:02,830 --> 00:10:04,700
So with that, if we save this,

188
00:10:04,700 --> 00:10:07,940
I see them here because I am not logged in

189
00:10:07,940 --> 00:10:12,002
and if I do log in this time with my admin,

190
00:10:12,002 --> 00:10:15,480
then indeed I see admin and profile

191
00:10:15,480 --> 00:10:17,660
and I can go to both pages,

192
00:10:17,660 --> 00:10:20,460
but I don't see sign up and log in anymore

193
00:10:20,460 --> 00:10:24,403
except for when I log out, then I do see these items again.

194
00:10:25,320 --> 00:10:28,650
So res locals is really useful for setting up

195
00:10:28,650 --> 00:10:32,580
such global data so that you don't have to pass it manually

196
00:10:32,580 --> 00:10:34,153
into all these templates.

197
00:10:35,040 --> 00:10:35,873
And of course,

198
00:10:35,873 --> 00:10:39,440
we cannot also use that in other places as well.

199
00:10:39,440 --> 00:10:44,440
Like in our routes, in our routes we are manually checking

200
00:10:44,580 --> 00:10:49,330
if a user is logged in or authorized in our get admin

201
00:10:49,330 --> 00:10:51,013
and get profile routes.

202
00:10:51,900 --> 00:10:54,840
Now, since we do that in our middleware already

203
00:10:54,840 --> 00:10:59,575
in that new custom middleware, we wrote this middleware.

204
00:10:59,575 --> 00:11:02,930
We don't need to do it again here in these routes

205
00:11:02,930 --> 00:11:06,894
res locals is also accessible in these routes

206
00:11:06,894 --> 00:11:11,320
because these routes come after our custom middleware,

207
00:11:11,320 --> 00:11:14,920
the order does matter here because the requests travels

208
00:11:14,920 --> 00:11:19,570
through all these middle wares in App.js from top to bottom.

209
00:11:19,570 --> 00:11:23,420
But here our custom middleware extract some data already

210
00:11:23,420 --> 00:11:25,970
and stores it in res locals.

211
00:11:25,970 --> 00:11:27,690
And they offer here in our routes

212
00:11:27,690 --> 00:11:31,240
res locals is set to these values.

213
00:11:31,240 --> 00:11:35,360
So therefore here in slash admin in this get route

214
00:11:35,360 --> 00:11:38,020
instead of again, looking into the session

215
00:11:38,020 --> 00:11:40,580
and even retrieving a user here,

216
00:11:40,580 --> 00:11:45,573
we can just check if not res locals is off,

217
00:11:47,686 --> 00:11:49,010
it's true here.

218
00:11:49,010 --> 00:11:51,910
So if that's not true, and we know we're not authenticated

219
00:11:53,200 --> 00:11:55,770
and we don't need to fetch a user here,

220
00:11:55,770 --> 00:12:00,770
instead here we just check if not res locals is admin

221
00:12:02,050 --> 00:12:04,690
in which case is sent back the 403 page

222
00:12:06,410 --> 00:12:08,680
and I need to return here.

223
00:12:08,680 --> 00:12:11,703
That's important so that this code doesn't execute.

224
00:12:12,580 --> 00:12:14,100
We should have done this before as well

225
00:12:14,100 --> 00:12:15,270
that was a tiny bug.

226
00:12:15,270 --> 00:12:17,130
You definitely have to return here

227
00:12:17,130 --> 00:12:18,800
so that this code doesn't run

228
00:12:19,850 --> 00:12:22,350
the same can be done in the profile page.

229
00:12:22,350 --> 00:12:24,650
We don't need to look into the session again.

230
00:12:24,650 --> 00:12:27,030
We could, but we don't have to we can look

231
00:12:27,030 --> 00:12:29,390
into res locals is off.

232
00:12:29,390 --> 00:12:32,480
And if this is false, hence the exclamation mark,

233
00:12:32,480 --> 00:12:34,613
I return the 401 page.

234
00:12:36,000 --> 00:12:39,230
So now again, if I save and I go back

235
00:12:39,230 --> 00:12:42,860
and manually try to access slash admin,

236
00:12:42,860 --> 00:12:46,570
I still get not authenticated because I'm not logged in

237
00:12:46,570 --> 00:12:49,410
but if I do log in with my user again, here,

238
00:12:49,410 --> 00:12:52,740
then I can visit those pages just fine.

239
00:12:52,740 --> 00:12:55,180
So that protection works as before,

240
00:12:55,180 --> 00:12:57,260
but now we're using res locals

241
00:12:57,260 --> 00:13:01,600
since we already set this in our custom middleware here,

242
00:13:01,600 --> 00:13:03,940
and that's another very useful feature

243
00:13:03,940 --> 00:13:07,760
you should be aware of when working with authentication,

244
00:13:07,760 --> 00:13:10,240
it's not authentication exclusive.

245
00:13:10,240 --> 00:13:13,630
You can use res locals for anything you want

246
00:13:13,630 --> 00:13:17,410
and you can write custom middle wares for anything you want.

247
00:13:17,410 --> 00:13:19,950
But here, especially for this use case,

248
00:13:19,950 --> 00:13:22,850
both features combined are very useful

249
00:13:22,850 --> 00:13:25,960
because now we can check the authentication

250
00:13:25,960 --> 00:13:28,120
and authorization status once,

251
00:13:28,120 --> 00:13:31,600
and then we stored it so that we can use the stored data

252
00:13:31,600 --> 00:13:35,310
in all our routes and all our templates

253
00:13:35,310 --> 00:13:37,120
without having to pass the data

254
00:13:37,120 --> 00:13:38,943
into the templates explicitly.

