1
00:00:02,050 --> 00:00:03,530
So finally,

2
00:00:03,530 --> 00:00:06,240
now that we've got the basic all flow into sessions, set up,

3
00:00:06,240 --> 00:00:11,050
let's work on the validation side, off the user input.

4
00:00:11,050 --> 00:00:12,870
And of course, just to be clear,

5
00:00:12,870 --> 00:00:14,580
if you try to submit the form,

6
00:00:14,580 --> 00:00:18,520
we got some validation here already built into the browser

7
00:00:18,520 --> 00:00:22,340
thanks to the special HTML attributes we added to our form

8
00:00:22,340 --> 00:00:26,140
input elements in the signup and login forms.

9
00:00:26,140 --> 00:00:29,440
We did add the mid-length max length

10
00:00:29,440 --> 00:00:32,890
and required attributes here.

11
00:00:32,890 --> 00:00:37,230
So we got some basic validation here, but for one,

12
00:00:37,230 --> 00:00:39,840
this can easily be disabled.

13
00:00:39,840 --> 00:00:43,870
If we have a user who knows how to use the dev tools like

14
00:00:43,870 --> 00:00:45,640
you, for example,

15
00:00:45,640 --> 00:00:50,000
that user can simply edit the loaded content here.

16
00:00:50,000 --> 00:00:54,820
I could remove the required attribute and all of a sudden

17
00:00:54,820 --> 00:00:57,570
I'm not getting a warning for that field anymore.

18
00:00:57,570 --> 00:01:00,260
And I could do that for all fields and then submit

19
00:01:00,260 --> 00:01:01,610
the empty form.

20
00:01:01,610 --> 00:01:05,379
And if we have a backend that's not prepared for this and

21
00:01:05,379 --> 00:01:09,150
that doesn't validate the user data on the backend,

22
00:01:09,150 --> 00:01:12,610
then this empty data, could be stored in a database,

23
00:01:12,610 --> 00:01:15,110
which is typically not what we want.

24
00:01:15,110 --> 00:01:17,710
That's why we should never trust our users.

25
00:01:17,710 --> 00:01:21,920
And always also validate the user input on the backend.

26
00:01:21,920 --> 00:01:22,940
On the front end,

27
00:01:22,940 --> 00:01:26,640
we just have the validation and those validation attributes

28
00:01:26,640 --> 00:01:30,240
to provide a better user experience to the majority of our

29
00:01:30,240 --> 00:01:34,000
users who will then see that they forgot to fill in a value

30
00:01:34,000 --> 00:01:35,130
in some fields,

31
00:01:35,130 --> 00:01:37,260
but it's not there to protect us

32
00:01:37,260 --> 00:01:41,220
against malicious or tricky users.

33
00:01:41,220 --> 00:01:43,810
So that's one reason why we want to have service side

34
00:01:43,810 --> 00:01:45,380
validation.

35
00:01:45,380 --> 00:01:47,830
But in addition, there are also a certain checks,

36
00:01:47,830 --> 00:01:50,440
which we can't run on the front end. For example,

37
00:01:50,440 --> 00:01:52,810
checking if a email address already exists,

38
00:01:52,810 --> 00:01:55,960
if we try to create a user with an email address that

39
00:01:55,960 --> 00:01:58,050
already exists in a database,

40
00:01:58,050 --> 00:02:00,430
that is something we don't know in the browser,

41
00:02:00,430 --> 00:02:03,300
that is something we have to check on the server instead,

42
00:02:03,300 --> 00:02:06,413
because that is where we communicate with the database.

43
00:02:08,009 --> 00:02:11,840
And therefore we need to add validation on the backend and

44
00:02:11,840 --> 00:02:15,520
the off controller in the signup function here

45
00:02:15,520 --> 00:02:20,470
before we call user signup and we store all that data.

46
00:02:20,470 --> 00:02:23,720
We want to validate that user input,

47
00:02:23,720 --> 00:02:27,440
and we want to perform various checks here. For example, I,

48
00:02:27,440 --> 00:02:31,260
first of all, want to check if all these fields are valid.

49
00:02:31,260 --> 00:02:34,220
Now we could write all the validation logic here

50
00:02:34,220 --> 00:02:35,410
in the controller,

51
00:02:35,410 --> 00:02:38,370
but as so often I'll work with a separate file

52
00:02:38,370 --> 00:02:42,090
in the util folder here, which I'll name validation JS,

53
00:02:42,090 --> 00:02:46,640
which should hold my validation related logic simply so that

54
00:02:46,640 --> 00:02:48,960
the auth controller can stay leaner.

55
00:02:48,960 --> 00:02:52,100
That's always the reason for splitting up our code,

56
00:02:52,100 --> 00:02:53,333
as you can tell by now.

57
00:02:54,360 --> 00:02:56,623
So in there I'll add a new function.

58
00:02:58,140 --> 00:03:02,720
UserDetailsAreValid sounds like a fitting name

59
00:03:02,720 --> 00:03:05,190
because that function should return true.

60
00:03:05,190 --> 00:03:08,823
If the provided data is valid and false otherwise.

61
00:03:09,830 --> 00:03:13,390
And here, I then expect to get the email, the password,

62
00:03:13,390 --> 00:03:18,023
the name, the street, the postal code, and the city,

63
00:03:19,160 --> 00:03:22,380
because that's the user data we're working with.

64
00:03:22,380 --> 00:03:25,480
And now it's up to you how you want to validate this.

65
00:03:25,480 --> 00:03:28,650
Here I will just return a Boolean value,

66
00:03:28,650 --> 00:03:32,460
which I derived by checking all these different parameter

67
00:03:32,460 --> 00:03:36,890
values for certain aspects. You could say, for example,

68
00:03:36,890 --> 00:03:40,150
an email is valid if it's set.

69
00:03:40,150 --> 00:03:45,150
So if it's truthy and email includes a @ symbol, let's say

70
00:03:48,700 --> 00:03:51,600
I'm checking if the email includes a @ symbol,

71
00:03:51,600 --> 00:03:54,410
which to me tells me that it's valid.

72
00:03:54,410 --> 00:03:55,790
So if we have email,

73
00:03:55,790 --> 00:03:58,370
if this is not undefined or anything like this,

74
00:03:58,370 --> 00:04:02,050
and it includes a @ symbol, I am happy.

75
00:04:02,050 --> 00:04:05,170
Of course a user could then still send something like just

76
00:04:05,170 --> 00:04:10,170
hi@unknown.com, which might not be

77
00:04:10,750 --> 00:04:12,940
a valid, existing email address.

78
00:04:12,940 --> 00:04:15,460
Bu this is something we can't check here.

79
00:04:15,460 --> 00:04:18,459
We would have to send a test email to that address

80
00:04:18,459 --> 00:04:20,140
to do that.

81
00:04:20,140 --> 00:04:23,070
But at least we ensure that some value was provided

82
00:04:23,070 --> 00:04:25,183
and that it looks like a email address.

83
00:04:27,490 --> 00:04:31,170
Then I also want to check if the password is set and

84
00:04:31,170 --> 00:04:36,170
password.trim.length is greater than five characters.

85
00:04:38,770 --> 00:04:42,400
The trim method when called on a string, which password is,

86
00:04:42,400 --> 00:04:45,610
will remove any excess white space at the beginning

87
00:04:45,610 --> 00:04:46,970
and the end of the string.

88
00:04:46,970 --> 00:04:50,810
And then length is a property we can call on any array

89
00:04:50,810 --> 00:04:53,940
and string to get the number of characters

90
00:04:53,940 --> 00:04:55,350
in the case of a string.

91
00:04:55,350 --> 00:04:57,720
And then I want to ensure that the password is

92
00:04:57,720 --> 00:04:59,560
at least six characters long.

93
00:04:59,560 --> 00:05:02,430
So I'm looking for a length greater than five

94
00:05:02,430 --> 00:05:06,287
or alternatively greater or equal than six.

95
00:05:08,260 --> 00:05:12,320
With that, I checked the two main credentials for validity.

96
00:05:12,320 --> 00:05:13,960
I also want to ensure the name street,

97
00:05:13,960 --> 00:05:15,920
postal and city are valid.

98
00:05:15,920 --> 00:05:18,220
So therefore next,

99
00:05:18,220 --> 00:05:22,080
I'll use the and operator to add another condition to this

100
00:05:22,080 --> 00:05:25,080
overall Boolean, which I'm deriving here,

101
00:05:25,080 --> 00:05:30,030
where I check that name is truthy and name.trim is not

102
00:05:31,580 --> 00:05:34,743
equal to an empty string, which means that is set.

103
00:05:37,100 --> 00:05:39,930
Now, if I temporarily reformat this,

104
00:05:39,930 --> 00:05:42,760
this is already getting really long.

105
00:05:42,760 --> 00:05:43,593
And for example,

106
00:05:43,593 --> 00:05:45,890
I'm going to repeat this logic for the name,

107
00:05:45,890 --> 00:05:48,373
for the street, postal and city fields.

108
00:05:49,430 --> 00:05:52,360
Therefore I'll add a utility function in here,

109
00:05:52,360 --> 00:05:57,360
which I'll name is Empty, where I get any value,

110
00:05:58,160 --> 00:06:00,380
no matter if it's a name or a street

111
00:06:00,380 --> 00:06:03,900
and I've returned true here, if not value.

112
00:06:03,900 --> 00:06:05,960
So if it's undefined

113
00:06:05,960 --> 00:06:10,960
or if value.trim equals an empty string.

114
00:06:13,200 --> 00:06:16,593
So the opposite logic of what I have down there.

115
00:06:17,510 --> 00:06:19,220
And with that is empty function.

116
00:06:19,220 --> 00:06:20,820
Instead of checking my name like this,

117
00:06:20,820 --> 00:06:24,863
I can check if not is empty for name.

118
00:06:25,940 --> 00:06:28,730
The exclamation mark is important because I want to have a

119
00:06:28,730 --> 00:06:31,593
name that's not fulfilling these conditions.

120
00:06:32,450 --> 00:06:37,387
And now we can quickly do the same with is empty street

121
00:06:37,387 --> 00:06:38,220
and so on.

122
00:06:38,220 --> 00:06:40,560
And therefore, we save a lot of time here

123
00:06:40,560 --> 00:06:43,240
because now we can just repeat

124
00:06:43,240 --> 00:06:46,720
this utility function and execute this utility function

125
00:06:46,720 --> 00:06:50,193
instead of writing the entire logic over and over again.

126
00:06:52,300 --> 00:06:55,660
And we can also take this logic

127
00:06:55,660 --> 00:06:58,300
and add another utility function,

128
00:06:58,300 --> 00:07:01,373
which will name userCredentialsAreValid.

129
00:07:06,870 --> 00:07:11,870
And here I return what I just cut and I get my email

130
00:07:11,950 --> 00:07:13,993
and password here.

131
00:07:15,130 --> 00:07:17,520
And then here and user details are valid.

132
00:07:17,520 --> 00:07:21,680
I will first check if user credentials are valid by calling

133
00:07:21,680 --> 00:07:24,630
this newly edit function and passing email and password

134
00:07:24,630 --> 00:07:28,820
to it. But now we have less code in here.

135
00:07:28,820 --> 00:07:30,460
And instead we distributed it

136
00:07:30,460 --> 00:07:33,950
across multiple other utility functions.

137
00:07:33,950 --> 00:07:34,783
And therefore here,

138
00:07:34,783 --> 00:07:37,473
we have quite readable code, I would say.

139
00:07:38,660 --> 00:07:42,130
Now it's this user details are valid function,

140
00:07:42,130 --> 00:07:45,920
which I want to expose outside of this file.

141
00:07:45,920 --> 00:07:50,820
And actually here there for all export this here,

142
00:07:50,820 --> 00:07:53,373
this function. User details are valid.

143
00:07:54,650 --> 00:07:56,593
And in the auth controller,

144
00:07:58,120 --> 00:08:03,120
we can get our user credentials are valid constant here

145
00:08:03,800 --> 00:08:08,260
by requiring going up one level util validation.

146
00:08:10,170 --> 00:08:12,900
And this is now a function which we can execute here

147
00:08:12,900 --> 00:08:15,770
to check the entered credentials.

148
00:08:15,770 --> 00:08:18,680
So here in the signup function,

149
00:08:18,680 --> 00:08:22,900
I will now check if user credentials are valid

150
00:08:22,900 --> 00:08:26,060
and I want to forward all the data I'm getting here.

151
00:08:26,060 --> 00:08:30,310
And if that's not the case, hence the exclamation mark.

152
00:08:30,310 --> 00:08:33,770
Then I know that we got incorrect input

153
00:08:33,770 --> 00:08:35,203
and then I want to return.

154
00:08:36,330 --> 00:08:38,610
So that no other code executes.

155
00:08:38,610 --> 00:08:43,250
And I want to redirect back to the signup page

156
00:08:43,250 --> 00:08:46,313
so that the user is able to enter correct data.

157
00:08:47,280 --> 00:08:50,690
Again, all the entered data will be lost with that,

158
00:08:50,690 --> 00:08:52,440
but we'll work on that in a second.

159
00:08:53,540 --> 00:08:55,980
For the moment, let's make sure we pass all the data

160
00:08:55,980 --> 00:08:59,230
that is expected by user credentials are valid

161
00:08:59,230 --> 00:09:01,390
to that function and therefore here,

162
00:09:01,390 --> 00:09:04,460
I now pass rec body email as a first value,

163
00:09:04,460 --> 00:09:07,530
then rec body password as a second value,

164
00:09:07,530 --> 00:09:10,770
rec body full name as a third value.

165
00:09:10,770 --> 00:09:15,450
And so on for all the values I'm getting here,

166
00:09:15,450 --> 00:09:19,823
postal and rec body city.

167
00:09:20,900 --> 00:09:22,290
Lets reformat this.

168
00:09:22,290 --> 00:09:25,360
And that's now how I called this utility function

169
00:09:25,360 --> 00:09:27,930
to validate whether we got correct credentials.

170
00:09:27,930 --> 00:09:30,880
And if we don't, I redirect.

171
00:09:30,880 --> 00:09:33,760
And actually user details are valid,

172
00:09:33,760 --> 00:09:35,180
is the more fitting name here

173
00:09:35,180 --> 00:09:36,760
because I'm not just verifying

174
00:09:36,760 --> 00:09:39,460
the credentials, but all the user data.

175
00:09:39,460 --> 00:09:41,063
So let's all the rename it here.

176
00:09:42,140 --> 00:09:43,950
Of course we could've kept the old name,

177
00:09:43,950 --> 00:09:47,253
but you want to use names that are as clear as possible.

178
00:09:48,940 --> 00:09:51,210
Now with that, we're almost there,

179
00:09:51,210 --> 00:09:53,550
but one important check is missing.

180
00:09:53,550 --> 00:09:57,340
The email address entered here in the first field has to

181
00:09:57,340 --> 00:09:59,450
match the confirm email address.

182
00:09:59,450 --> 00:10:01,550
And we're not checking for this right now.

183
00:10:02,730 --> 00:10:06,633
To check for this invalidation JS. I'll add a new function.

184
00:10:07,950 --> 00:10:11,550
Email is confirmed we could say,

185
00:10:11,550 --> 00:10:14,640
and here we get the email and the confirm email

186
00:10:14,640 --> 00:10:18,430
as parameter values and there returned true,

187
00:10:18,430 --> 00:10:22,623
if email is equal to confirm email, just like that.

188
00:10:23,970 --> 00:10:27,050
Now I also want to use this function outside of this file.

189
00:10:27,050 --> 00:10:28,230
And therefore instead of

190
00:10:28,230 --> 00:10:31,360
just exporting user details are valid.

191
00:10:31,360 --> 00:10:32,730
I'll export an object,

192
00:10:32,730 --> 00:10:36,760
which has a user details are valid key,

193
00:10:36,760 --> 00:10:40,560
which points at the user details are valid function.

194
00:10:40,560 --> 00:10:42,950
But which now alls in addition gets

195
00:10:42,950 --> 00:10:44,480
an email is confirmed key,

196
00:10:44,480 --> 00:10:46,980
which points that the email is confirmed function.

197
00:10:48,930 --> 00:10:49,773
Like this.

198
00:10:51,120 --> 00:10:53,450
And now back in the auth controller,

199
00:10:53,450 --> 00:10:58,080
we are actually importing the validation object

200
00:10:58,080 --> 00:11:02,160
with various validation functions that are part of it.

201
00:11:02,160 --> 00:11:06,660
And hence here I now call validation.UserDetailsAreValid,

202
00:11:07,960 --> 00:11:12,040
but I want to combine this check with a number check.

203
00:11:12,040 --> 00:11:15,550
If not user details are valid, we make it in here,

204
00:11:15,550 --> 00:11:18,660
but I also want to make it in there as an alternative

205
00:11:18,660 --> 00:11:21,760
and hence combined with the or operator

206
00:11:21,760 --> 00:11:25,400
if validation, email is confirmed fails.

207
00:11:25,400 --> 00:11:29,720
So if not validation, email is confirmed

208
00:11:29,720 --> 00:11:32,393
and here the exclamation mark is always important.

209
00:11:33,570 --> 00:11:38,510
And here I then pass in a rec.body.email and direct.body.

210
00:11:38,510 --> 00:11:41,393
And then with square brackets, confirm email.

211
00:11:42,390 --> 00:11:44,150
Why square brackets?

212
00:11:44,150 --> 00:11:48,380
Because in the signup EJS file in that form,

213
00:11:48,380 --> 00:11:53,030
this confirm email field has a name of confirmed dash email.

214
00:11:53,030 --> 00:11:55,580
So that's the key which we can use to get access

215
00:11:55,580 --> 00:11:58,173
to the entered data, to the entered value.

216
00:11:59,390 --> 00:12:02,770
The problem with that is that dashes are not allowed

217
00:12:02,770 --> 00:12:06,510
in JavaScript property names. Or they are allowed,

218
00:12:06,510 --> 00:12:10,080
but not when extracting them with the dot notation.

219
00:12:10,080 --> 00:12:13,460
Hence we can't use .confirm-email.

220
00:12:13,460 --> 00:12:15,010
This would not be allowed,

221
00:12:15,010 --> 00:12:17,410
but as an alternative to the dot notation,

222
00:12:17,410 --> 00:12:19,840
you can also use square brackets.

223
00:12:19,840 --> 00:12:22,890
And then the property name, which you want to access.

224
00:12:22,890 --> 00:12:24,370
So this is totally fine.

225
00:12:24,370 --> 00:12:25,850
And this will give us access

226
00:12:25,850 --> 00:12:27,803
to the confirm email that was entered.

227
00:12:28,890 --> 00:12:29,723
So with that,

228
00:12:29,723 --> 00:12:34,290
we added some validation to this sign up action.

229
00:12:34,290 --> 00:12:35,590
It's not all though.

230
00:12:35,590 --> 00:12:37,530
Even if the enter data is correct,

231
00:12:37,530 --> 00:12:41,700
we want to ensure that the user did not try to sign up

232
00:12:41,700 --> 00:12:45,343
with an email address that's already stored in the database.

233
00:12:46,620 --> 00:12:47,453
To ensure this,

234
00:12:47,453 --> 00:12:49,820
we can go to our user model,

235
00:12:49,820 --> 00:12:54,820
and there already have the get user with same email method.

236
00:12:54,860 --> 00:12:58,310
This returns us any user that is identified that has

237
00:12:58,310 --> 00:13:02,620
the same email address we can build up on this method

238
00:13:02,620 --> 00:13:04,450
with another method.

239
00:13:04,450 --> 00:13:09,450
For example, named exists already, which returns true,

240
00:13:09,550 --> 00:13:12,480
if the user we're trying to create exists already

241
00:13:12,480 --> 00:13:13,483
in the database.

242
00:13:15,000 --> 00:13:17,600
For this in here with the, this keyword,

243
00:13:17,600 --> 00:13:20,800
we can call get user with same email.

244
00:13:20,800 --> 00:13:22,100
You can use the, this keyword,

245
00:13:22,100 --> 00:13:24,500
not just to access properties,

246
00:13:24,500 --> 00:13:26,960
but also to access and call methods

247
00:13:26,960 --> 00:13:28,560
that exist on an object.

248
00:13:28,560 --> 00:13:30,340
Here I'm calling this method

249
00:13:31,330 --> 00:13:34,110
and this year we'll look for a user

250
00:13:34,110 --> 00:13:35,453
with that email address.

251
00:13:36,410 --> 00:13:38,680
Now it will return a promise and I'm interested

252
00:13:38,680 --> 00:13:40,610
in the result of that promise.

253
00:13:40,610 --> 00:13:44,630
So we can use async here and then a weight,

254
00:13:44,630 --> 00:13:48,973
the result of this, and we get our existing user here then.

255
00:13:50,010 --> 00:13:52,940
Now if we do find an existing user,

256
00:13:52,940 --> 00:13:55,410
we want to return true here because then a user

257
00:13:55,410 --> 00:13:57,800
with that email exists already.

258
00:13:57,800 --> 00:14:01,423
If we don't find an existing user, we want to return false.

259
00:14:02,460 --> 00:14:06,920
So here I will check if existing user, if this is truthy,

260
00:14:06,920 --> 00:14:09,813
if we have a user, then I'll return true.

261
00:14:11,060 --> 00:14:12,900
Else if we don't make it into this,

262
00:14:12,900 --> 00:14:14,840
if check here all returned false.

263
00:14:14,840 --> 00:14:16,543
So then we don't have a user.

264
00:14:19,020 --> 00:14:22,330
Now back in the off controller,

265
00:14:22,330 --> 00:14:27,330
after verifying the general input, before we call, sign up,

266
00:14:27,440 --> 00:14:30,290
I want to use my user object,

267
00:14:30,290 --> 00:14:33,160
which was already created here.

268
00:14:33,160 --> 00:14:38,000
And actually we might want to cut it and only created after

269
00:14:38,000 --> 00:14:40,600
we validated all the input.

270
00:14:40,600 --> 00:14:44,920
So we created here now after the input validation,

271
00:14:44,920 --> 00:14:48,060
and then on this user, before we sign up,

272
00:14:48,060 --> 00:14:50,453
I want to call exists already.

273
00:14:51,870 --> 00:14:54,350
Now this yields a promise.

274
00:14:54,350 --> 00:14:59,130
So I want to await it and store the result in a constant

275
00:14:59,130 --> 00:15:01,513
that can be named exists already.

276
00:15:02,910 --> 00:15:04,490
Like this.

277
00:15:04,490 --> 00:15:08,280
And if exists already as true,

278
00:15:08,280 --> 00:15:11,430
then we know that we don't want to continue with signup

279
00:15:11,430 --> 00:15:14,260
because we already have a user with that email

280
00:15:14,260 --> 00:15:15,800
in the database.

281
00:15:15,800 --> 00:15:19,150
So then I want to return so that no other code executes

282
00:15:19,150 --> 00:15:23,243
and just as before we want to redirect back to /sign up.

283
00:15:24,110 --> 00:15:27,333
So that the user has to enter a new data there.

284
00:15:28,780 --> 00:15:30,530
Now in exists already,

285
00:15:30,530 --> 00:15:33,550
we under the hood reach out to the database

286
00:15:33,550 --> 00:15:37,520
and that could fail so we'll actually grab all that code

287
00:15:37,520 --> 00:15:40,800
and move it into this try catch block here.

288
00:15:40,800 --> 00:15:43,360
So that'd be handle any errors that might occur

289
00:15:43,360 --> 00:15:46,320
with that existing try-catch block.

290
00:15:46,320 --> 00:15:48,240
We could have also added a new block,

291
00:15:48,240 --> 00:15:51,513
but since we have that block anyways, we can just reuse it.

292
00:15:53,090 --> 00:15:57,410
So now with that, we're checking for user existence

293
00:15:57,410 --> 00:16:00,160
and that's all good and nice, but at the moment,

294
00:16:00,160 --> 00:16:04,700
we're not providing any feedback on our forms here.

295
00:16:04,700 --> 00:16:08,360
If validation fails outside of the front end validation,

296
00:16:08,360 --> 00:16:10,960
if I try to log in, for example,

297
00:16:10,960 --> 00:16:12,900
with the incorrect password,

298
00:16:12,900 --> 00:16:16,220
then this page is just reload it, but I get no feedback.

299
00:16:16,220 --> 00:16:19,540
And my input data is lost and that's of course not good.

300
00:16:19,540 --> 00:16:20,870
So in the next lecture,

301
00:16:20,870 --> 00:16:23,940
we'll make sure that we show such a error message here

302
00:16:23,940 --> 00:16:26,590
and that we keep the user input.

303
00:16:26,590 --> 00:16:28,170
As always, and as before,

304
00:16:28,170 --> 00:16:30,040
and in the future of this section,

305
00:16:30,040 --> 00:16:32,010
definitely try this on your own first,

306
00:16:32,010 --> 00:16:33,723
before we implement it together.

