1
00:00:00,930 --> 00:00:05,850
So in order to authenticate clearly we're going to need some new database functions, we're going to

2
00:00:05,850 --> 00:00:11,820
need to be able to get a user, which means we probably need to insert, update and delete users.

3
00:00:12,210 --> 00:00:14,560
We probably want to be able to get all users.

4
00:00:14,580 --> 00:00:18,770
And finally, we'll need an actual routine to perform the authentication itself.

5
00:00:19,050 --> 00:00:20,600
So let's get some of this stuff out of the way.

6
00:00:20,700 --> 00:00:27,360
So I'm in my post Glasgow file, which is inside DB Repo, which is inside repository, which is inside

7
00:00:27,360 --> 00:00:28,050
packages.

8
00:00:28,410 --> 00:00:34,560
And I'm going to create a new function and the first one I'll do is to get a user func Amster Postgres

9
00:00:34,710 --> 00:00:35,490
DB Repo.

10
00:00:35,490 --> 00:00:39,450
So it has that receiver and I'll call this get user by ID

11
00:00:42,300 --> 00:00:45,210
and I'm probably going to want to get user by email or something as well.

12
00:00:45,220 --> 00:00:50,340
But we'll start with this one and I'll take one parameter to this, which will be ID, which is an end,

13
00:00:50,580 --> 00:00:56,160
and I'll return to things models, dot user and potentially an error.

14
00:00:58,890 --> 00:01:05,280
So as is always the case, we're going to have our context, which I'll copy from the function above

15
00:01:05,280 --> 00:01:13,050
paste in here, and then I'll write my query and my query will be query is assigned the value of select

16
00:01:13,260 --> 00:01:18,550
and then I want to look at my model's table or models just to find out exactly what fields are in there.

17
00:01:19,320 --> 00:01:21,630
So I'd first name, last name, email.

18
00:01:21,690 --> 00:01:24,990
Let's do that ID first name.

19
00:01:24,990 --> 00:01:26,550
Last name that are spell name.

20
00:01:26,550 --> 00:01:26,820
Right.

21
00:01:32,050 --> 00:01:37,990
Email and what else is their first name, last name, password access level created an updated and we

22
00:01:37,990 --> 00:01:39,710
don't need the password, but I'll grab it anyway.

23
00:01:40,180 --> 00:01:40,930
Password.

24
00:01:42,030 --> 00:01:43,080
Access level.

25
00:01:45,360 --> 00:01:53,520
Created and updated at, created at, updated at and I go on to a new line.

26
00:01:56,080 --> 00:02:02,920
From users where ID equals and I put a placeholder in, so that should give me my basic query.

27
00:02:06,120 --> 00:02:10,350
Now, since I know I'm going to get at most one row, I can use Queretaro context.

28
00:02:10,350 --> 00:02:22,260
So Roe is a sign the value of IMDB DOT Queretaro context, which takes the context X and requires the

29
00:02:22,260 --> 00:02:28,140
query string query and it requires the placeholders, which in this case is just one ID.

30
00:02:28,650 --> 00:02:30,810
And that gives me my value of Roe.

31
00:02:32,190 --> 00:02:37,050
Now that I have that, I can actually check for an error and scan the ROE into a variable.

32
00:02:37,060 --> 00:02:39,690
So let's create a variable var user.

33
00:02:39,970 --> 00:02:43,830
I'll call it you because you shouldn't name it the name of the actual table.

34
00:02:44,730 --> 00:02:50,100
You as a model's user and error is assigned the value of.

35
00:02:59,250 --> 00:03:09,240
Robots scan and I'm going to scan it into the variable I just created, so a reference to you ID a reference

36
00:03:09,240 --> 00:03:12,390
to you first name, and let's just duplicate this a few times.

37
00:03:14,950 --> 00:03:15,700
Last name.

38
00:03:18,860 --> 00:03:19,430
Email.

39
00:03:21,500 --> 00:03:22,310
The committer.

40
00:03:24,180 --> 00:03:24,900
Password.

41
00:03:27,560 --> 00:03:30,290
And duplicator owing three more times.

42
00:03:32,620 --> 00:03:37,420
Access level created at an updated at.

43
00:03:41,200 --> 00:03:43,000
If our error is not equal to nil.

44
00:03:47,040 --> 00:03:52,710
Return you error, otherwise return, you know.

45
00:03:53,760 --> 00:03:58,980
OK, so there is one function that allows me to get a user ID, which I know I'm going to need at some

46
00:03:58,980 --> 00:04:05,250
point returns a user ID.

47
00:04:05,640 --> 00:04:12,210
OK, I'll just make sure we got all of the fields in their email password access level created updated

48
00:04:12,210 --> 00:04:12,480
at.

49
00:04:14,080 --> 00:04:16,180
Email, password access, yes, we have them all.

50
00:04:16,720 --> 00:04:20,770
All right, so that one should work now that we've created this, of course, we have to add it to our

51
00:04:20,770 --> 00:04:23,350
repository, otherwise we have no access to it.

52
00:04:23,360 --> 00:04:28,620
So let's go to our repository and paste in that new one.

53
00:04:29,110 --> 00:04:29,460
Good.

54
00:04:30,280 --> 00:04:31,420
So that's our first function.

55
00:04:31,630 --> 00:04:39,730
Our second function should be to modify a user func M Sturr Postgrads DB Repo Update user.

56
00:04:40,540 --> 00:04:41,800
That will be the name of the function.

57
00:04:41,800 --> 00:04:48,700
It will take one parameter which is a named you and will be of type models dot user and it will return

58
00:04:48,700 --> 00:04:49,210
an error.

59
00:04:52,430 --> 00:05:01,220
So context, as usual, copy and paste that read our query query is a sign the value of in tactics

60
00:05:03,620 --> 00:05:10,630
update users set and I'm not going to change the ID, obviously, but it will be first name equal to

61
00:05:10,640 --> 00:05:11,210
dollar sign.

62
00:05:11,220 --> 00:05:21,970
One last name equal to dollar sign to email, equal to dollar sign three password.

63
00:05:22,010 --> 00:05:26,150
I'm not going to do the password this way because there's a different way of handling passwords and

64
00:05:26,150 --> 00:05:27,410
we'll leave that out entirely.

65
00:05:27,410 --> 00:05:27,980
Right now.

66
00:05:28,860 --> 00:05:33,620
Access level equals dollar sign for.

67
00:05:34,490 --> 00:05:39,740
And the only other thing to worry about is updated at equal to dollar sign five.

68
00:05:40,640 --> 00:05:48,200
OK, so there's our query and we can execute that query using our appropriate method from the database

69
00:05:48,210 --> 00:05:48,440
pool.

70
00:05:48,510 --> 00:05:56,300
So the method is called Emerg DB dot exact context.

71
00:05:57,860 --> 00:05:59,720
An exact context returns.

72
00:06:01,520 --> 00:06:06,760
A result and an error, so it leads to things we don't care about the result, but we do care about

73
00:06:06,760 --> 00:06:07,210
the error.

74
00:06:09,860 --> 00:06:14,630
And we're going to execute what in this context, while the parameters it requires first it requires

75
00:06:14,630 --> 00:06:18,890
the context, then it requires the query, then it requires the arguments so we can do it this way.

76
00:06:19,720 --> 00:06:21,050
This is our context.

77
00:06:21,050 --> 00:06:26,960
Our query is query, and I'm going to put these on separate lines just so it's a little easier to read.

78
00:06:27,260 --> 00:06:40,220
The first argument will be you dot first name, then you dot last name, then you dot email, then you

79
00:06:40,220 --> 00:06:41,350
dot access level.

80
00:06:42,590 --> 00:06:49,640
Then the last one is just the time that this was updated, which is just time dot now and that should

81
00:06:49,640 --> 00:06:50,540
take care of that.

82
00:06:50,690 --> 00:06:52,010
But we have to check for the error.

83
00:06:52,580 --> 00:06:58,130
If error is not equal to nil return error, otherwise we're just returning null.

84
00:07:00,700 --> 00:07:05,650
So there is our one for updating user, which we're not using yet, but we will at some point probably

85
00:07:06,700 --> 00:07:09,410
update a user in the database.

86
00:07:10,840 --> 00:07:14,990
Finally, let's look at this one where we actually have to authenticate.

87
00:07:16,000 --> 00:07:22,390
This one's a little harder, really not that hard, but we'll be doing some things you haven't seen

88
00:07:22,390 --> 00:07:24,340
yet, including hashed passwords.

89
00:07:25,540 --> 00:07:30,220
When we store our information about the user in the database, we are never, ever going to store the

90
00:07:30,220 --> 00:07:31,420
password as clear.

91
00:07:31,420 --> 00:07:38,470
Text instead will store the password using a hash using some of the functionality built into the standard

92
00:07:38,470 --> 00:07:38,980
library.

93
00:07:39,370 --> 00:07:46,570
So that means we have to somehow when we're authenticating, compare what the user typed against a hash

94
00:07:46,570 --> 00:07:47,380
in the database.

95
00:07:47,410 --> 00:07:53,620
They're going to type a username and a password, and we're going to take that password and see if the

96
00:07:53,620 --> 00:07:59,200
hash in our database actually corresponds to what it should if they've typed in the right password.

97
00:07:59,920 --> 00:08:02,630
This might sound a little confusing, but it's not that tough.

98
00:08:02,650 --> 00:08:03,400
So let's get started.

99
00:08:03,700 --> 00:08:07,270
We'll create a new function, which I will call func.

100
00:08:07,450 --> 00:08:10,750
It has to be in the receiver of Postgrads DB Repo again.

101
00:08:11,200 --> 00:08:12,460
I will call it authenticate.

102
00:08:15,210 --> 00:08:22,020
And what I want to authenticate are basically two things email and test to password, which will both

103
00:08:22,020 --> 00:08:23,340
come in the form of strings.

104
00:08:24,420 --> 00:08:27,020
And what is going to return are three things.

105
00:08:27,120 --> 00:08:32,190
I'm going to return on into a string and potentially an error.

106
00:08:34,110 --> 00:08:38,850
OK, so we have this function created, but now we need to populate it with meaningful data.

107
00:08:38,880 --> 00:08:44,520
As always, I'm going to copy the context and paste it in here and let's get started.

108
00:08:45,000 --> 00:08:51,150
So the first thing I'm going to do is create an empty variable called ID and this will hold the ID of

109
00:08:51,150 --> 00:08:54,760
the authenticated user if things return as the way they should.

110
00:08:54,780 --> 00:08:58,560
In other words, if they put the right information in there, then I have a typo up here.

111
00:08:58,560 --> 00:08:59,430
So let's fix that.

112
00:09:00,610 --> 00:09:01,070
That's better.

113
00:09:01,930 --> 00:09:07,210
So I created a variable to hold the ID of the authenticated user, and I don't know that until they

114
00:09:07,210 --> 00:09:08,380
successfully authenticate.

115
00:09:09,190 --> 00:09:15,070
So let's try this, the next thing I'm going to want is ver it's going to be called hashed password,

116
00:09:16,180 --> 00:09:17,670
and this will be a string as well.

117
00:09:18,100 --> 00:09:24,170
So the hashed password, which is really hard to say, that's going to hold obviously a hashed password.

118
00:09:24,730 --> 00:09:29,710
Now I want to query the database, first of all, to see if I can find this user.

119
00:09:29,930 --> 00:09:36,640
OK, so I'm going to create a row variable because I'm using the DB query row context.

120
00:09:36,950 --> 00:09:41,090
I mean, I know I'm going to get most one row from the query I'm about to type.

121
00:09:42,430 --> 00:09:48,370
So it requires the context and it requires a query which I will go as follows.

122
00:09:48,370 --> 00:09:56,890
Select ID password from users where email equals dollar sign what?

123
00:09:59,120 --> 00:10:05,300
And the one substitution in that query is obviously the email, which I've already passed as a parameter

124
00:10:05,300 --> 00:10:08,510
to this function, so that will potentially give me my row.

125
00:10:09,350 --> 00:10:14,810
And then, of course, I have to say I have to scan that information into some variables.

126
00:10:14,940 --> 00:10:15,860
I just created those.

127
00:10:15,890 --> 00:10:18,290
I will scan those as follows.

128
00:10:19,100 --> 00:10:26,420
Error is assigned the value of rodent scan and I'm going to scan into the ID variable and the hashed

129
00:10:26,420 --> 00:10:27,410
password variable.

130
00:10:28,580 --> 00:10:29,810
And then I got a check for an error.

131
00:10:30,950 --> 00:10:41,150
If error is not equal to nil, I'll just return my ID, my string, which will be empty in this case.

132
00:10:41,480 --> 00:10:42,050
And the error.

133
00:10:44,370 --> 00:10:49,950
Otherwise, keep going, it's not called air, it's cold or otherwise keep going.

134
00:10:50,460 --> 00:10:56,430
So at this point, if I've passed that test, if they've entered a valid email and that matches an email

135
00:10:56,430 --> 00:11:01,110
in my system, now I need to compare their password with my password.

136
00:11:03,710 --> 00:11:09,420
And we do that as follows, error equals and this is a built in package, right?

137
00:11:09,470 --> 00:11:15,560
Part of the standard library, it's called Decrypt, which is one of the very useful encryption algorithms

138
00:11:15,560 --> 00:11:17,050
or encryption projects out there.

139
00:11:17,870 --> 00:11:22,660
And all I'm going to do is take advantage of a built in function, compare hash and password.

140
00:11:23,180 --> 00:11:24,620
And that takes two arguments.

141
00:11:24,620 --> 00:11:31,220
The HASP hashed password as a slice of bytes and the password I'm testing against, which is a slice

142
00:11:31,220 --> 00:11:32,550
slice of bytes as well.

143
00:11:33,650 --> 00:11:38,570
So I will test first of all, I need to cast to a slice of bytes.

144
00:11:41,640 --> 00:11:43,380
And I'm going to cast the variable.

145
00:11:44,710 --> 00:11:45,820
Hashed password.

146
00:11:48,840 --> 00:11:49,710
Against.

147
00:11:52,310 --> 00:11:53,600
As a slice of bite's.

148
00:11:55,320 --> 00:12:03,540
The test password, so all I'm doing here is saying here is the hash password that I pulled out of the

149
00:12:03,540 --> 00:12:11,250
database, does this hash match the hash that you test or you create by running it against test password,

150
00:12:11,250 --> 00:12:13,320
which is whatever the user typed into the form?

151
00:12:13,620 --> 00:12:18,080
If they did, then all is good and were successful and we can continue.

152
00:12:18,540 --> 00:12:22,470
Otherwise it's not successful and we need to do something else.

153
00:12:23,700 --> 00:12:28,800
So let's first of all, test that error if error is equal.

154
00:12:28,800 --> 00:12:29,370
Exactly.

155
00:12:29,370 --> 00:12:33,060
To be creped error and this has some errors built into it.

156
00:12:33,060 --> 00:12:34,020
So be creped.

157
00:12:34,140 --> 00:12:35,010
Better spell it right.

158
00:12:35,710 --> 00:12:36,570
B creped.

159
00:12:40,190 --> 00:12:45,830
Error, mismatched hash and password, that's a constant that's built into the package in the standard

160
00:12:45,830 --> 00:12:46,290
library.

161
00:12:46,580 --> 00:12:53,660
So if the error is I tried to do the comparison between these two and they don't match, then what I

162
00:12:53,660 --> 00:12:55,700
want to do well, I want to return something.

163
00:12:56,090 --> 00:13:02,990
Otherwise, if the error is something else, if error is not equal to nil, then some other error took

164
00:13:02,990 --> 00:13:04,640
place and I needed to return something.

165
00:13:04,640 --> 00:13:08,600
So I'll return zero and I'll have an empty string.

166
00:13:08,600 --> 00:13:12,320
And whatever the error is in this case, I will return.

167
00:13:14,190 --> 00:13:14,770
Zero.

168
00:13:15,750 --> 00:13:21,000
And I'll return a new error errors, new

169
00:13:23,910 --> 00:13:31,380
incorrect password, actually, that's has to start with the lowercase character in order to be formatted

170
00:13:31,380 --> 00:13:33,140
the way the go wants things to be formatted.

171
00:13:33,390 --> 00:13:34,380
So look at what we've done here.

172
00:13:34,620 --> 00:13:36,770
First of all, we create our context as normal.

173
00:13:37,080 --> 00:13:42,030
Then we declare two variables that we're going to use to store information that we get from the database.

174
00:13:42,360 --> 00:13:48,600
We query the database and we store those two values in that we get from the database ID and password

175
00:13:48,600 --> 00:13:50,990
in the variable ID and hash password.

176
00:13:51,420 --> 00:13:57,360
Then we take advantage of the built in package decrypt to compare the hash that we grab from the database

177
00:13:57,810 --> 00:14:02,210
against a hash created from the password that the user typed into the form.

178
00:14:02,790 --> 00:14:07,500
If we have a mismatch, in other words, there are no errors, but they don't match.

179
00:14:07,620 --> 00:14:13,050
We generate a new error called incorrect password and send that back with dummy information for the

180
00:14:13,050 --> 00:14:13,970
first two parameters.

181
00:14:14,430 --> 00:14:19,790
Otherwise, if there's another error that's not a mismatch password, we just return the error.

182
00:14:20,010 --> 00:14:26,160
And now if we get past all of that, then we are ready to return the necessary information because the

183
00:14:26,160 --> 00:14:27,420
user can be logged in.

184
00:14:27,810 --> 00:14:33,480
So we'll return the ID will return the hashed password from the database, which we may use.

185
00:14:33,480 --> 00:14:38,490
We may not, but I want to be able to do that if I need to, and which are nil because there was no

186
00:14:38,490 --> 00:14:38,790
error.

187
00:14:39,510 --> 00:14:41,010
So let's give this a comment.

188
00:14:44,220 --> 00:14:47,040
Authenticate, authenticate a user.

189
00:14:47,550 --> 00:14:48,810
Alice, do this one as well.

190
00:14:49,260 --> 00:14:54,450
We already gave that one a comment, but we need to put that into our database repository.

191
00:14:54,470 --> 00:15:01,380
So let's open the repository and paste that in there and go back to postgrads and grab the authenticate.

192
00:15:03,490 --> 00:15:05,860
And pass that back into our repository.

193
00:15:07,170 --> 00:15:11,950
Now let's try running the application to make sure that everything runs and compiles nicely and we have

194
00:15:11,950 --> 00:15:12,660
something here.

195
00:15:13,320 --> 00:15:18,010
I use test tube repo as database as written argument test.

196
00:15:18,010 --> 00:15:20,830
She does not implement missing the authenticate method.

197
00:15:21,730 --> 00:15:23,240
OK, so what did I get wrong?

198
00:15:23,470 --> 00:15:24,490
There's the authenticate.

199
00:15:24,970 --> 00:15:28,570
Let's go back to Postgres authenticators right there.

200
00:15:31,050 --> 00:15:31,740
Here it is.

201
00:15:33,330 --> 00:15:37,260
There are no errors, so let's copy that and go back to our repository.

202
00:15:38,340 --> 00:15:39,420
Maybe I just didn't save it.

203
00:15:39,660 --> 00:15:40,890
I'll paste it in to be sure.

204
00:15:41,820 --> 00:15:44,810
Save let's try running this again.

205
00:15:47,650 --> 00:15:50,700
Cannot use and untested literal type O testing.

206
00:15:50,860 --> 00:15:55,420
We have to put these in our test tube repo as well, of course, silly me.

207
00:15:55,510 --> 00:15:57,970
All right, so let's go open up our test tube repo.

208
00:16:00,650 --> 00:16:07,130
And we need to have three new methods in there, so we need to have func M test DB repo.

209
00:16:10,370 --> 00:16:19,610
And the first one we want is get user by ID and it takes a parameter ID event and it returns a model's

210
00:16:19,940 --> 00:16:29,090
user and potentially an error and we'll just have that for you is models dot user return, you know?

211
00:16:31,040 --> 00:16:32,440
So that's the first one taken care of.

212
00:16:32,450 --> 00:16:33,740
Let's take care of the second one.

213
00:16:34,160 --> 00:16:36,280
So that was get user by ID update user.

214
00:16:36,290 --> 00:16:36,940
So here we are.

215
00:16:36,950 --> 00:16:45,770
Let's just copy this to save some typing, go back to our test repo and paste that in there and change

216
00:16:45,770 --> 00:16:53,720
it to a test DB repo and that returns an error return nil and finally authenticate.

217
00:16:54,320 --> 00:16:56,290
So we'll create a dummy method for that as well.

218
00:16:59,910 --> 00:17:10,890
And go back to our test repo, paste that in, change it to a test DB repo and return an international

219
00:17:10,890 --> 00:17:13,980
return, won a string and empty string and an error.

220
00:17:14,010 --> 00:17:14,400
No.

221
00:17:16,070 --> 00:17:16,870
And that should do it.

222
00:17:16,880 --> 00:17:18,560
So now I should be able to stop this.

223
00:17:18,620 --> 00:17:22,610
Clear the screen, run it and without errors.

224
00:17:24,840 --> 00:17:25,320
Perfect.

225
00:17:25,830 --> 00:17:31,650
All right, so the next step is to complete the changes necessary on our login screen to have it point

226
00:17:31,650 --> 00:17:38,070
to an actual form, to create a route for the handler, for the post of that form, and then to create

227
00:17:38,070 --> 00:17:39,040
the necessary handler.

228
00:17:39,060 --> 00:17:44,010
And at that point, we're almost ready to actually authenticate a user and we'll take care of that in

229
00:17:44,010 --> 00:17:44,970
the next few lectures.
