1
1

00:00:00,880  -->  00:00:02,480
<v Jose>Hi and welcome back.</v>
2

2

00:00:02,480  -->  00:00:04,380
In this video we're going to start adding
3

3

00:00:04,380  -->  00:00:06,923
user registration to our app.
4

4

00:00:07,910  -->  00:00:11,880
Up til now we've been able to add alerts and stores,
5

5

00:00:11,880  -->  00:00:15,400
but no matter how many people are using our application
6

6

00:00:15,400  -->  00:00:18,130
they're all going to see the same alerts.
7

7

00:00:18,130  -->  00:00:20,940
That is because we've got no way in our app
8

8

00:00:20,940  -->  00:00:23,473
of distinguishing between multiple users.
9

9

00:00:25,380  -->  00:00:27,330
For example, if we were to put this out there
10

10

00:00:27,330  -->  00:00:28,990
and share it with users,
11

11

00:00:28,990  -->  00:00:31,940
and then all of the users were to go over
12

12

00:00:31,940  -->  00:00:35,480
to say our alerts page, at the moment I don't have any,
13

13

00:00:35,480  -->  00:00:39,149
but they would all see the same alerts.
14

14

00:00:39,149  -->  00:00:41,300
What we have to do is we have to
15

15

00:00:41,300  -->  00:00:43,930
allow users to create an account,
16

16

00:00:43,930  -->  00:00:47,087
and then we have to keep track of the users
17

17

00:00:47,087  -->  00:00:50,550
and allow them to login.
18

18

00:00:50,550  -->  00:00:54,170
When they login we will be able to show them their alerts
19

19

00:00:54,170  -->  00:00:57,120
as opposed to everybody's alerts.
20

20

00:00:57,120  -->  00:01:00,110
Also having user details will allow us
21

21

00:01:00,110  -->  00:01:02,290
to notify them individually
22

22

00:01:02,290  -->  00:01:05,783
when the alerts reach the desired price.
23

23

00:01:07,160  -->  00:01:09,050
So this video going to be a bit longer.
24

24

00:01:09,050  -->  00:01:12,600
We're going to be doing a lot of work in this one.
25

25

00:01:12,600  -->  00:01:15,840
We'll begin by going over to our templates
26

26

00:01:15,840  -->  00:01:17,723
and add a new folder.
27

27

00:01:18,590  -->  00:01:20,370
I'm gonna call this Users.
28

28

00:01:20,370  -->  00:01:23,400
And then here I'm going to add an HTML file called
29

29

00:01:23,400  -->  00:01:25,490
register.html.
30

30

00:01:25,490  -->  00:01:29,900
This is the file that is going to contain our form.
31

31

00:01:29,900  -->  00:01:32,740
I'm going to just go over to something like
32

32

00:01:32,740  -->  00:01:33,803
a new alert,
33

33

00:01:35,020  -->  00:01:37,483
copy it because the form is going to be similar.
34

34

00:01:38,360  -->  00:01:39,410
But instead of creating an alert
35

35

00:01:39,410  -->  00:01:41,363
we're gonna call it register.
36

36

00:01:43,640  -->  00:01:46,430
And we're gonna make a few changes here.
37

37

00:01:46,430  -->  00:01:50,300
We're gonna have two things that the user needs to enter,
38

38

00:01:50,300  -->  00:01:53,683
their email and the password that they want.
39

39

00:01:54,640  -->  00:01:58,920
Now, it's important that your input has a type of password
40

40

00:01:58,920  -->  00:02:01,470
as that is going to hide away the characters
41

41

00:02:01,470  -->  00:02:02,700
as you type on it.
42

42

00:02:02,700  -->  00:02:05,407
Everything else is gonna stay the same,
43

43

00:02:05,407  -->  00:02:07,190
so all that we need to have in here
44

44

00:02:07,190  -->  00:02:09,870
is just this section with this form.
45

45

00:02:09,870  -->  00:02:14,800
And now we can move over and start creating our view.
46

46

00:02:14,800  -->  00:02:16,370
For a view we're gonna right click it
47

47

00:02:16,370  -->  00:02:17,720
and create a new Python file.
48

48

00:02:17,720  -->  00:02:19,663
And I'm gonna call it user.py.
49

49

00:02:21,560  -->  00:02:23,410
And before we do anything here
50

50

00:02:23,410  -->  00:02:25,660
I'm just going to go over to app.py
51

51

00:02:25,660  -->  00:02:28,110
and I'm going to make sure to add
52

52

00:02:28,110  -->  00:02:30,523
the user blueprint that we're about to create.
53

53

00:02:34,640  -->  00:02:37,010
And now that we're here we'll do something
54

54

00:02:37,010  -->  00:02:38,583
that we forgot to do earlier.
55

55

00:02:39,830  -->  00:02:44,100
And it is this blueprint, the store blueprint.
56

56

00:02:44,100  -->  00:02:45,550
So we'll also add it in here.
57

57

00:02:46,630  -->  00:02:47,463
That's good.
58

58

00:02:48,870  -->  00:02:51,190
Let's move over to our user views
59

59

00:02:51,190  -->  00:02:53,180
and start coding it.
60

60

00:02:53,180  -->  00:02:55,280
We'll need the user imports
61

61

00:02:57,830  -->  00:03:00,280
including this new one that we've not seen yet
62

62

00:03:00,280  -->  00:03:01,210
called session.
63

63

00:03:01,210  -->  00:03:02,690
We're gonna need that in just a moment.
64

64

00:03:02,690  -->  00:03:04,810
And I'll explain what the session is
65

65

00:03:04,810  -->  00:03:07,600
as we do this.
66

66

00:03:07,600  -->  00:03:10,070
We'll also need redirect.
67

67

00:03:10,070  -->  00:03:12,100
And of course we will need
68

68

00:03:13,420  -->  00:03:16,453
our user model that we will be creating in just a moment.
69

69

00:03:18,690  -->  00:03:20,040
Let's create our blueprint,
70

70

00:03:24,645  -->  00:03:27,812
and then let's add our first endpoint.
71

71

00:03:38,322  -->  00:03:40,380
Nothing new here,
72

72

00:03:40,380  -->  00:03:41,410
pretty much exactly the same
73

73

00:03:41,410  -->  00:03:44,684
as creating an alert or a new store.
74

74

00:03:44,684  -->  00:03:45,560
What we've done is we have created
75

75

00:03:45,560  -->  00:03:47,560
this structure of our endpoint
76

76

00:03:47,560  -->  00:03:49,323
and now we have to fill it in.
77

77

00:03:50,721  -->  00:03:54,220
And so when the browser arrives at our page
78

78

00:03:54,220  -->  00:03:57,361
we're going to render this register.html form.
79

79

00:03:57,361  -->  00:03:59,900
When the form is submitted we're gonna
80

80

00:03:59,900  -->  00:04:03,156
receive a post request with some form data,
81

81

00:04:03,156  -->  00:04:05,620
so we're gonna deal with it inside this if statement.
82

82

00:04:05,620  -->  00:04:07,243
We're gonna receive two fields,
83

83

00:04:08,660  -->  00:04:11,593
the email and the password field.
84

84

00:04:14,800  -->  00:04:18,490
And this password is just gonna be plain text.
85

85

00:04:18,490  -->  00:04:20,480
We're gonna talk about password encryption
86

86

00:04:20,480  -->  00:04:22,137
later on in this course,
87

87

00:04:22,137  -->  00:04:23,780
so don't worry about perceiving passwords in plain text
88

88

00:04:23,780  -->  00:04:26,150
if you're concerned about security.
89

89

00:04:26,150  -->  00:04:28,993
We'll be working around that in just a moment.
90

90

00:04:30,170  -->  00:04:33,200
Then we're going to try to do something,
91

91

00:04:33,200  -->  00:04:35,308
and I'm not sure if we've looked at
92

92

00:04:35,308  -->  00:04:36,810
try except blocks in Python.
93

93

00:04:36,810  -->  00:04:39,270
But essentially what a try except block allows us to do
94

94

00:04:39,270  -->  00:04:41,640
is to try to run a code block,
95

95

00:04:41,640  -->  00:04:44,780
and if there an error or an exception that happens
96

96

00:04:44,780  -->  00:04:48,170
during that block, then we can catch it a the end
97

97

00:04:48,170  -->  00:04:51,810
and do something different rather than crashing our app.
98

98

00:04:51,810  -->  00:04:52,680
So what were going to do is
99

99

00:04:52,680  -->  00:04:55,990
we're going to try to register the user,
100

100

00:04:55,990  -->  00:04:58,650
so we're gonna do something like user.register user
101

101

00:05:01,200  -->  00:05:03,250
passing in the email and password.
102

102

00:05:03,250  -->  00:05:06,340
And if we have an error
103

103

00:05:07,610  -->  00:05:10,140
then we're gonna return the errors message.
104

104

00:05:10,140  -->  00:05:13,050
So normally if you encounter an error
105

105

00:05:13,050  -->  00:05:16,120
when you are performing some code in Flask
106

106

00:05:16,120  -->  00:05:20,353
what you'll get out is you'll get a pretty nasty error page.
107

107

00:05:21,270  -->  00:05:23,610
Instead what we're gonna do is if we encounter an error
108

108

00:05:23,610  -->  00:05:25,670
we're gonna just return the message
109

109

00:05:25,670  -->  00:05:27,423
included within the error.
110

110

00:05:28,350  -->  00:05:33,350
In order to do that, we're going to have to do this.
111

111

00:05:33,850  -->  00:05:37,370
So what this does is try to catch all the exceptions,
112

112

00:05:37,370  -->  00:05:40,430
or any exception that happens during this code block
113

113

00:05:40,430  -->  00:05:44,360
we're gonna call it e inside this other block
114

114

00:05:44,360  -->  00:05:46,750
so that we can access its properties.
115

115

00:05:46,750  -->  00:05:48,830
So there's gonna be e.message
116

116

00:05:48,830  -->  00:05:51,500
will access the message property of e,
117

117

00:05:51,500  -->  00:05:54,210
which will be the exception that happened in this block
118

118

00:05:54,210  -->  00:05:55,043
if it happened.
119

119

00:05:55,043  -->  00:05:57,550
If it didn't happen, then we'll just run this
120

120

00:05:57,550  -->  00:05:59,053
and never run this.
121

121

00:06:00,330  -->  00:06:02,800
Now when we register a user
122

122

00:06:02,800  -->  00:06:07,041
we're going to have something saved into our database.
123

123

00:06:07,041  -->  00:06:11,610
But it would also be nice if we could
124

124

00:06:11,610  -->  00:06:16,020
somehow store that information in the user's browser,
125

125

00:06:16,020  -->  00:06:18,040
store some information in the user's browser
126

126

00:06:18,040  -->  00:06:20,360
so that when they come back to our site
127

127

00:06:20,360  -->  00:06:22,743
we know that they are logged in.
128

128

00:06:24,040  -->  00:06:25,950
We're gonna look at this in more detail
129

129

00:06:25,950  -->  00:06:27,910
when we look at logging in.
130

130

00:06:27,910  -->  00:06:30,530
But essentially when a user registers,
131

131

00:06:30,530  -->  00:06:31,980
after they finish registering
132

132

00:06:32,914  -->  00:06:33,900
they should already be logged in
133

133

00:06:33,900  -->  00:06:36,573
so they don't have to register and then login.
134

134

00:06:37,970  -->  00:06:42,430
When we talk about logging in what we really mean is
135

135

00:06:42,430  -->  00:06:44,950
every time the user visits our page
136

136

00:06:44,950  -->  00:06:48,210
we should be able to tell that that user
137

137

00:06:48,210  -->  00:06:51,613
is the user that registered, and not somebody else.
138

138

00:06:52,960  -->  00:06:55,400
It's impossible to do that unless
139

139

00:06:55,400  -->  00:06:58,210
the browser sends us some data
140

140

00:06:58,210  -->  00:07:01,700
that allows us to identify that browser
141

141

00:07:01,700  -->  00:07:04,510
as the browser that performed this registration.
142

142

00:07:04,510  -->  00:07:06,893
The browser that sent us the data in the form.
143

143

00:07:08,550  -->  00:07:11,420
So when the browser sends us the data in the form
144

144

00:07:11,420  -->  00:07:13,160
we will register that user
145

145

00:07:13,160  -->  00:07:16,252
and then we will send the browser back some data,
146

146

00:07:16,252  -->  00:07:20,120
and that browser in future accesses to our website
147

147

00:07:20,120  -->  00:07:22,400
will send us that data, and with it
148

148

00:07:22,400  -->  00:07:24,453
we'll be able to tell that that is the same browser
149

149

00:07:24,453  -->  00:07:27,400
that sent us the initial form data.
150

150

00:07:27,400  -->  00:07:29,060
So there is a back and forth there
151

151

00:07:29,060  -->  00:07:31,990
between us and the browser sending this data
152

152

00:07:31,990  -->  00:07:34,003
that allows us to uniquely identify it.
153

153

00:07:35,000  -->  00:07:38,150
And that data is a cookie.
154

154

00:07:38,150  -->  00:07:39,740
So if you don't know what cookies are,
155

155

00:07:39,740  -->  00:07:43,079
they're just pieces of data that are stored on the browser.
156

156

00:07:43,079  -->  00:07:46,990
And alongside the data we also store
157

157

00:07:46,990  -->  00:07:51,230
what webpage sets the cookie.
158

158

00:07:51,230  -->  00:07:55,417
So in this case it's gonna be 127.0.0.1;5000
159

159

00:07:55,417  -->  00:07:57,860
that's our current site.
160

160

00:07:57,860  -->  00:07:59,640
So we're gonna set a cookie
161

161

00:07:59,640  -->  00:08:02,370
and set that that is the address of the cookie.
162

162

00:08:02,370  -->  00:08:05,850
Whenever the browser makes a request to that webpage
163

163

00:08:05,850  -->  00:08:08,290
it will automatically include the cookie.
164

164

00:08:08,290  -->  00:08:10,470
So the user doesn't have to do anything
165

165

00:08:10,470  -->  00:08:12,480
and we have to do very little.
166

166

00:08:12,480  -->  00:08:14,520
We just have to send that data
167

167

00:08:14,520  -->  00:08:17,943
and then every time it will be returned back to us.
168

168

00:08:19,820  -->  00:08:23,410
Flask has a very nice way of dealing with that data
169

169

00:08:23,410  -->  00:08:25,023
which is by using this session.
170

170

00:08:25,900  -->  00:08:30,000
A session is a piece of data that is stored
171

171

00:08:30,000  -->  00:08:32,422
inside our application
172

172

00:08:32,422  -->  00:08:37,422
and it is stored for each user differently.
173

173

00:08:37,750  -->  00:08:41,880
So each user will have a separate, individual session.
174

174

00:08:41,880  -->  00:08:45,960
And what Flask does is when we get one of those cookies,
175

175

00:08:45,960  -->  00:08:50,920
Flask will tell us the session that is associated to it.
176

176

00:08:50,920  -->  00:08:52,860
So when a browser sends us the cookie
177

177

00:08:52,860  -->  00:08:56,660
Flask will say okay, the session is for this user
178

178

00:08:56,660  -->  00:08:59,910
and we can store whatever we want in that session.
179

179

00:08:59,910  -->  00:09:04,013
So we will say session, email, equal email.
180

180

00:09:05,000  -->  00:09:08,255
And what this does is once we've registered the user
181

181

00:09:08,255  -->  00:09:12,380
we're going to store the users email inside the session,
182

182

00:09:12,380  -->  00:09:14,030
the session is like a dictionary,
183

183

00:09:14,890  -->  00:09:18,410
so that in the future when the browser sends us the cookie
184

184

00:09:18,410  -->  00:09:21,840
Flask will automatically get the session
185

185

00:09:21,840  -->  00:09:23,920
that is already saved into our application
186

186

00:09:23,920  -->  00:09:27,140
and populate the user's email that we've set here
187

187

00:09:27,140  -->  00:09:29,010
in future requests.
188

188

00:09:29,010  -->  00:09:31,800
That means that if the user sends us the cookie
189

189

00:09:31,800  -->  00:09:34,550
in something like an alert and point for example
190

190

00:09:34,550  -->  00:09:37,110
we could access session email
191

191

00:09:37,110  -->  00:09:39,850
and it would be the same email that we sent
192

192

00:09:39,850  -->  00:09:43,103
when that browser sent us the registration request.
193

193

00:09:45,000  -->  00:09:48,070
So just to recap real quick before we move on,
194

194

00:09:48,070  -->  00:09:49,750
we send the user a cookie
195

195

00:09:49,750  -->  00:09:52,630
and that cookie has a piece of data that allows Flask
196

196

00:09:52,630  -->  00:09:56,170
to identify what session it's related to.
197

197

00:09:56,170  -->  00:09:58,088
When the cookie is received by our application
198

198

00:09:58,088  -->  00:10:00,250
Flask will populate the session
199

199

00:10:00,250  -->  00:10:02,483
with the data that we've set earlier on.
200

200

00:10:03,560  -->  00:10:05,573
So that's how it keeps track of that.
201

201

00:10:07,756  -->  00:10:12,756
Now this register user method has to be created,
202

202

00:10:12,980  -->  00:10:14,480
it doesn't exist yet.
203

203

00:10:14,480  -->  00:10:17,590
And of course this session email
204

204

00:10:17,590  -->  00:10:19,460
will be populated accordingly
205

205

00:10:19,460  -->  00:10:22,210
if this does not return an exception.
206

206

00:10:22,210  -->  00:10:24,560
If we get an exception here
207

207

00:10:24,560  -->  00:10:26,860
then we will jump immediately to this block
208

208

00:10:26,860  -->  00:10:27,973
and this will not run.
209

209

00:10:29,550  -->  00:10:32,886
Finally we're also going to return email just for now
210

210

00:10:32,886  -->  00:10:36,010
so that when a registration succeeds
211

211

00:10:36,010  -->  00:10:37,950
we can see something that tells us
212

212

00:10:37,950  -->  00:10:40,350
as the developer that it went well.
213

213

00:10:40,350  -->  00:10:42,520
Eventually we'll be returning something else here.
214

214

00:10:42,520  -->  00:10:44,530
You can say something like thank you for registering
215

215

00:10:44,530  -->  00:10:45,680
or something like that.
216

216

00:10:46,800  -->  00:10:49,120
The next problem is that in exception
217

217

00:10:49,120  -->  00:10:50,773
does not have a message property.
218

218

00:10:51,980  -->  00:10:54,140
So instead of using a generic exception
219

219

00:10:54,140  -->  00:10:55,970
that comes built in in Python
220

220

00:10:55,970  -->  00:10:58,250
we're going to create our own exception class
221

221

00:10:58,250  -->  00:10:59,920
that will contain a message.
222

222

00:10:59,920  -->  00:11:01,733
So we're gonna call that UserError
223

223

00:11:04,560  -->  00:11:06,903
and we do have to import that.
224

224

00:11:11,530  -->  00:11:14,870
However, because we're gonna have many different user errors
225

225

00:11:14,870  -->  00:11:16,710
that's gonna be like user not found,
226

226

00:11:16,710  -->  00:11:20,680
or password incorrect, or email with a bad format,
227

227

00:11:20,680  -->  00:11:22,230
there's gonna be a few of them.
228

228

00:11:22,230  -->  00:11:24,330
So what we're gonna do is we're gonna have
229

229

00:11:25,276  -->  00:11:27,050
a set of user errors.
230

230

00:11:27,050  -->  00:11:29,053
And we're gonna say UserErrors.UserError.
231

231

00:11:31,394  -->  00:11:34,210
This is gonna make a bit more sense as we move along.
232

232

00:11:34,210  -->  00:11:36,260
Don't worry too much about it.
233

233

00:11:36,260  -->  00:11:37,543
But this is our endpoint.
234

234

00:11:38,732  -->  00:11:40,020
And what we've done here is
235

235

00:11:40,020  -->  00:11:42,810
we've started at what the user sees
236

236

00:11:42,810  -->  00:11:45,959
and now we're moving down and down into our application
237

237

00:11:45,959  -->  00:11:48,040
by creating this view
238

238

00:11:48,040  -->  00:11:51,280
and now we're gonna move over and create the model.
239

239

00:11:51,280  -->  00:11:54,430
And then we'll be creating the errors and so on.
240

240

00:11:54,430  -->  00:11:58,400
So I like starting at what the user sees
241

241

00:11:58,400  -->  00:12:01,400
and defining how that's gonna be used
242

242

00:12:01,400  -->  00:12:04,580
before moving into implementation details.
243

243

00:12:04,580  -->  00:12:06,120
What I've defined here is
244

244

00:12:06,120  -->  00:12:09,550
I want a very simple way of registering a user in the model.
245

245

00:12:09,550  -->  00:12:12,016
I wanna be able to say user.register user,
246

246

00:12:12,016  -->  00:12:16,150
puts in an email and password, and that should either
247

247

00:12:16,150  -->  00:12:18,290
save the user to the database no problem
248

248

00:12:18,290  -->  00:12:20,483
or return an error.
249

249

00:12:22,500  -->  00:12:25,943
Now we have to go into the user model and create it.
250

250

00:12:27,040  -->  00:12:29,050
Notice though that for models user
251

251

00:12:29,050  -->  00:12:32,400
we're importing two things, user and user errors.
252

252

00:12:32,400  -->  00:12:34,670
So what we are gonna do in this model
253

253

00:12:34,670  -->  00:12:36,290
is we are going to learn about something new
254

254

00:12:36,290  -->  00:12:37,990
in Python that we've not looked at yet,
255

255

00:12:37,990  -->  00:12:41,520
and I'm gonna create a new Python package called user.
256

256

00:12:41,520  -->  00:12:42,810
And here we're going to create
257

257

00:12:42,810  -->  00:12:45,057
a new Python file called user.py,
258

258

00:12:45,057  -->  00:12:49,623
and we're also gonna create a new Python file called errors.
259

259

00:12:52,530  -->  00:12:54,183
Alright, so now we have that.
260

260

00:12:55,020  -->  00:12:57,570
In the user model we're going to define
261

261

00:12:57,570  -->  00:13:00,436
everything that we need in order to use
262

262

00:13:00,436  -->  00:13:03,400
a user in our application.
263

263

00:13:03,400  -->  00:13:07,350
So for now we'll have the UID,
264

264

00:13:07,350  -->  00:13:09,100
we're gonna have data classes,
265

265

00:13:09,100  -->  00:13:11,030
we're gonna have some typing,
266

266

00:13:11,030  -->  00:13:13,650
we're gonna have the model,
267

267

00:13:13,650  -->  00:13:15,530
we're gonna need the database,
268

268

00:13:15,530  -->  00:13:18,310
and we're gonna need also a couple other things.
269

269

00:13:18,310  -->  00:13:20,733
But we're gonna start with this just for now.
270

270

00:13:21,687  -->  00:13:23,733
We'll set the data class first of all,
271

271

00:13:26,230  -->  00:13:29,570
and then we'll define the things that a user needs.
272

272

00:13:29,570  -->  00:13:32,630
So we need a collection, which is going to be a string
273

273

00:13:32,630  -->  00:13:34,220
not in the init method.
274

274

00:13:34,220  -->  00:13:37,180
And the default is gonna be users,
275

275

00:13:37,180  -->  00:13:39,020
then it's gonna have an email,
276

276

00:13:39,020  -->  00:13:40,620
then it's gonna have a password,
277

277

00:13:42,620  -->  00:13:45,710
and finally an id_id property,
278

278

00:13:45,710  -->  00:13:49,500
which doesn't have a default value
279

279

00:13:49,500  -->  00:13:51,053
but it has a default factory.
280

280

00:13:53,390  -->  00:13:54,890
There we go.
281

281

00:13:54,890  -->  00:13:58,812
So that is our init method essentially created.
282

282

00:13:58,812  -->  00:13:59,980
It'll take an email and a password
283

283

00:13:59,980  -->  00:14:02,300
and optionally an _id field,
284

284

00:14:02,300  -->  00:14:04,380
but normally it will just be generated
285

285

00:14:04,380  -->  00:14:06,223
automatically by this function.
286

286

00:14:07,740  -->  00:14:09,603
Then we're gonna create a method,
287

287

00:14:11,190  -->  00:14:14,470
which is gonna be a class method called find by email.
288

288

00:14:14,470  -->  00:14:16,280
And the reason I'm making a separate one
289

289

00:14:16,280  -->  00:14:19,570
and not using the ones that are coming from model
290

290

00:14:19,570  -->  00:14:22,440
is because this one is also gonna try something.
291

291

00:14:22,440  -->  00:14:26,384
It's gonna try to return find one by of email
292

292

00:14:26,384  -->  00:14:29,650
using the email property that this gets passed.
293

293

00:14:29,650  -->  00:14:30,790
But if it fails
294

294

00:14:32,580  -->  00:14:34,470
with a type error because that's what'll happen
295

295

00:14:34,470  -->  00:14:36,790
if this doesn't exist in the database,
296

296

00:14:36,790  -->  00:14:39,083
then we're gonna raise a user error.
297

297

00:14:42,400  -->  00:14:45,460
Something like a user with this email was not found
298

298

00:14:45,460  -->  00:14:46,620
or something like that.
299

299

00:14:46,620  -->  00:14:49,200
Notice that that doesn't exist yet, but it will.
300

300

00:14:49,200  -->  00:14:51,150
And here what I'm defining is
301

301

00:14:51,150  -->  00:14:56,150
I would like to be able to raise one of these custom errors,
302

302

00:14:56,160  -->  00:14:58,500
or custom exceptions, when we fail
303

303

00:14:58,500  -->  00:15:01,003
to find a user on the database.
304

304

00:15:02,240  -->  00:15:04,407
And that method is going to be used
305

305

00:15:04,407  -->  00:15:09,030
by this register user method that we are gonna want.
306

306

00:15:09,030  -->  00:15:11,500
And that takes in an email and a password
307

307

00:15:11,500  -->  00:15:14,540
and it's gonna return a Boolean.
308

308

00:15:14,540  -->  00:15:15,720
The first thing this is going to do
309

309

00:15:15,720  -->  00:15:19,160
is it's going to check whether the email that the user
310

310

00:15:19,160  -->  00:15:21,520
is trying to register with is a valid email.
311

311

00:15:21,520  -->  00:15:23,663
I.e., it has the appropriate format.
312

312

00:15:29,160  -->  00:15:31,880
And if it doesn't then we're going to return
313

313

00:15:31,880  -->  00:15:33,433
an invalid email error.
314

314

00:15:38,160  -->  00:15:39,820
Okay, so there's a couple of new things here
315

315

00:15:39,820  -->  00:15:41,273
that we're going to import.
316

316

00:15:43,520  -->  00:15:46,771
We'll say from common utils import utils,
317

317

00:15:46,771  -->  00:15:47,604
that's where it's gonna live.
318

318

00:15:47,604  -->  00:15:51,970
And from the models user errors
319

319

00:15:54,650  -->  00:15:56,517
we're gonna import user errors.
320

320

00:15:58,219  -->  00:15:59,193
Okay?
321

321

00:16:00,740  -->  00:16:02,360
There we have that.
322

322

00:16:02,360  -->  00:16:04,740
Now if the email is valid
323

323

00:16:04,740  -->  00:16:08,880
then the next step is to see if the user already exists.
324

324

00:16:08,880  -->  00:16:13,880
So we'll say try to do a cls find by email.
325

325

00:16:18,100  -->  00:16:21,870
Now this method here is going to
326

326

00:16:21,870  -->  00:16:25,913
either return a user, which has been found in the database.
327

327

00:16:26,984  -->  00:16:29,360
Or it's going to raise an error
328

328

00:16:29,360  -->  00:16:32,090
saying the user could not be found.
329

329

00:16:32,090  -->  00:16:36,380
If the user can be found, that means that it already exists.
330

330

00:16:36,380  -->  00:16:38,570
So we don't want to create a new one.
331

331

00:16:38,570  -->  00:16:41,170
What we will do if this succeeds
332

332

00:16:41,170  -->  00:16:43,780
is we'll say, we'll raise a user error
333

333

00:16:43,780  -->  00:16:45,573
saying user already registered.
334

334

00:16:49,330  -->  00:16:54,310
Otherwise, if we get something like a user not found error
335

335

00:16:54,310  -->  00:16:57,710
which is what this raises,
336

336

00:16:57,710  -->  00:17:00,800
we're then going to create a user.
337

337

00:17:00,800  -->  00:17:04,583
And this may seem like a bit of a backward thing,
338

338

00:17:06,150  -->  00:17:08,710
we're actually doing what the method wants to do
339

339

00:17:08,710  -->  00:17:11,850
inside an except block, but that is find in Python.
340

340

00:17:11,850  -->  00:17:14,940
We're trying to do something
341

341

00:17:14,940  -->  00:17:19,330
and this is our positive scenario
342

342

00:17:19,330  -->  00:17:23,063
where the user tries to register but they already exist.
343

343

00:17:24,060  -->  00:17:26,513
If they already exist we just return an error.
344

344

00:17:26,513  -->  00:17:29,410
And otherwise if we get to the end
345

345

00:17:29,410  -->  00:17:32,360
and there was an error, meaning the user was not found,
346

346

00:17:32,360  -->  00:17:35,040
then we are gonna create a user
347

347

00:17:35,040  -->  00:17:36,360
and save it to MongoDB.
348

348

00:17:36,360  -->  00:17:38,260
We actually don't need the user equal.
349

349

00:17:39,190  -->  00:17:42,110
Notice that you could rewrite this
350

350

00:17:42,110  -->  00:17:45,274
so that it doesn't use a try except.
351

351

00:17:45,274  -->  00:17:47,802
But the resulting code is much longer
352

352

00:17:47,802  -->  00:17:51,773
and you do have to change this method as well.
353

353

00:17:52,700  -->  00:17:56,200
So I think this is a good way of going about it.
354

354

00:17:56,200  -->  00:17:57,870
Now the last thing we do need,
355

355

00:17:57,870  -->  00:18:00,220
of course because this is a model
356

356

00:18:00,220  -->  00:18:03,723
is we need the json method which returns a dictionary.
357

357

00:18:06,170  -->  00:18:08,490
And this is going to return
358

358

00:18:08,490  -->  00:18:10,483
all of the properties of the user.
359

359

00:18:15,738  -->  00:18:18,150
And remember this is only to be used
360

360

00:18:18,150  -->  00:18:19,730
when saving to the database.
361

361

00:18:19,730  -->  00:18:22,949
We are never going to return the user's json
362

362

00:18:22,949  -->  00:18:26,350
in our application because it contains the user's password.
363

363

00:18:26,350  -->  00:18:28,340
And we don't wanna be sharing that publicly
364

364

00:18:28,340  -->  00:18:29,373
with anybody else.
365

365

00:18:30,680  -->  00:18:33,080
There are a couple things we now need to create.
366

366

00:18:34,160  -->  00:18:37,030
Oh actually we don't need database here, my bad.
367

367

00:18:37,030  -->  00:18:40,300
Or list for now.
368

368

00:18:40,300  -->  00:18:42,020
We need to create the utils,
369

369

00:18:42,020  -->  00:18:44,270
and we need to create the user errors.
370

370

00:18:44,270  -->  00:18:46,240
Let's start with the utils.
371

371

00:18:46,240  -->  00:18:48,680
I'm gonna go over to common, right click it,
372

372

00:18:48,680  -->  00:18:50,846
Python file and create utils.py.
373

373

00:18:50,846  -->  00:18:55,281
And in here we're gonna have a class utils
374

374

00:18:55,281  -->  00:18:59,740
in which a static method, email is valid,
375

375

00:18:59,740  -->  00:19:00,680
is going to exist.
376

376

00:19:00,680  -->  00:19:04,150
It's gonna take a string and it's gonna return a Boolean
377

377

00:19:04,150  -->  00:19:07,350
saying whether the email has a valid format or not.
378

378

00:19:07,350  -->  00:19:09,340
We're gonna use the regex module
379

379

00:19:10,900  -->  00:19:13,410
in order to determine whether the email is valid.
380

380

00:19:13,410  -->  00:19:16,370
So we'll create an email address matcher,
381

381

00:19:16,370  -->  00:19:17,523
that's just a pattern.
382

382

00:19:20,320  -->  00:19:22,860
And this pattern is going to be
383

383

00:19:22,860  -->  00:19:27,860
something that starts with a set of words, or dashes,
384

384

00:19:30,332  -->  00:19:34,140
and there's gonna have at least one word or a dash,
385

385

00:19:34,140  -->  00:19:36,960
or sorry this is a character or dash.
386

386

00:19:36,960  -->  00:19:39,090
Then it's gonna have an at sign,
387

387

00:19:39,090  -->  00:19:44,090
and then it's going to have more characters or dashes,
388

388

00:19:45,378  -->  00:19:49,593
then it's gonna have a period.
389

389

00:19:50,440  -->  00:19:52,330
And it's going to have many of those.
390

390

00:19:52,330  -->  00:19:56,830
And eventually it's going to end with a set of characters
391

391

00:19:56,830  -->  00:19:59,280
and that's going to be the end of the string, so.
392

392

00:19:59,280  -->  00:20:02,680
A bit of a complicated irregular expression here.
393

393

00:20:02,680  -->  00:20:06,070
This character means the start of a string,
394

394

00:20:06,070  -->  00:20:08,350
and this character means the end of the string.
395

395

00:20:08,350  -->  00:20:10,240
When you have a regular expression pattern
396

396

00:20:10,240  -->  00:20:13,030
that is fully contained between these two characters
397

397

00:20:13,030  -->  00:20:17,230
it means that the email string cannot have anything else.
398

398

00:20:17,230  -->  00:20:22,230
So this stuff here must match the entire string.
399

399

00:20:22,590  -->  00:20:25,200
If it doesn't, it has anything more
400

400

00:20:25,200  -->  00:20:27,670
that would not match this entire string
401

401

00:20:27,670  -->  00:20:31,140
as the whole variable, it won't match
402

402

00:20:31,140  -->  00:20:35,543
because it has to reach the end and the start of the string.
403

403

00:20:36,460  -->  00:20:39,100
Then we've got words and dashes,
404

404

00:20:39,100  -->  00:20:41,310
sorry letters and dashes, any amount,
405

405

00:20:41,310  -->  00:20:45,730
for example Jose, that is letters.
406

406

00:20:45,730  -->  00:20:50,730
Jose pricing would also be letters and dashes.
407

407

00:20:51,000  -->  00:20:55,090
Then it's got the at sign, which would be an at sign.
408

408

00:20:55,090  -->  00:21:00,090
And then it's got letters and dashes or periods.
409

409

00:21:01,090  -->  00:21:05,430
For example, google.co.
410

410

00:21:05,430  -->  00:21:07,250
This is letters and dashes or periods,
411

411

00:21:07,250  -->  00:21:09,100
and it's got multiple of those groups.
412

412

00:21:09,100  -->  00:21:11,620
So this is letters and dashes and periods.
413

413

00:21:11,620  -->  00:21:13,010
This is letters and dashes and periods,
414

414

00:21:13,010  -->  00:21:14,760
but doesn't have dashes or periods,
415

415

00:21:17,210  -->  00:21:19,500
sorry that's the letters and dashes and periods.
416

416

00:21:19,500  -->  00:21:22,990
And eventually it's also got just letters at the end,
417

417

00:21:22,990  -->  00:21:24,513
for example uk.
418

418

00:21:25,580  -->  00:21:27,800
And it must be at the end of the string,
419

419

00:21:27,800  -->  00:21:30,980
this character must be the last one in the string.
420

420

00:21:30,980  -->  00:21:33,580
So this is how we're matching this sort of email.
421

421

00:21:33,580  -->  00:21:35,890
This is not a perfect email matcher
422

422

00:21:36,940  -->  00:21:40,680
because as you know some emails can have other characters,
423

423

00:21:40,680  -->  00:21:43,050
especially nowadays where emails are getting
424

424

00:21:43,050  -->  00:21:45,080
more and more Unicode friendly,
425

425

00:21:45,080  -->  00:21:47,250
you can have lots of other stuff in them.
426

426

00:21:47,250  -->  00:21:48,840
But for now it'll do.
427

427

00:21:48,840  -->  00:21:51,410
And you can always find better
428

428

00:21:51,410  -->  00:21:53,350
email matchers on the internet.
429

429

00:21:53,350  -->  00:21:54,870
They can be really long though,
430

430

00:21:54,870  -->  00:21:57,420
so I didn't want to write it out for you guys here.
431

431

00:21:59,574  -->  00:22:00,480
And then we're going to return true
432

432

00:22:00,480  -->  00:22:05,480
if the email matcher matches this email variable
433

433

00:22:06,600  -->  00:22:09,750
that we've received, otherwise we're gonna return false.
434

434

00:22:09,750  -->  00:22:11,160
This is just a short cut
435

435

00:22:11,995  -->  00:22:14,388
return to the operator here in Python.
436

436

00:22:14,388  -->  00:22:17,503
So true is that, otherwise false.
437

437

00:22:19,350  -->  00:22:22,250
Finally were going to move over to our errors,
438

438

00:22:22,250  -->  00:22:24,730
and we're gonna create a user error class
439

439

00:22:24,730  -->  00:22:26,580
which is gonna inherit from exception.
440

440

00:22:26,580  -->  00:22:28,140
And it's going to define an innate method
441

441

00:22:28,140  -->  00:22:29,763
that takes in a message.
442

442

00:22:32,834  -->  00:22:37,179
Now all our other classes like user not found error,
443

443

00:22:37,179  -->  00:22:39,408
is going to inherit from user error
444

444

00:22:39,408  -->  00:22:41,023
and it's gonna do nothing.
445

445

00:22:43,460  -->  00:22:46,978
And similarly for our user already registered error
446

446

00:22:46,978  -->  00:22:49,523
which is gonna inherit from user error.
447

447

00:22:51,005  -->  00:22:54,120
And for our invalid email error
448

448

00:22:55,600  -->  00:22:58,630
which is also going to inherit from user and do nothing.
449

449

00:22:58,630  -->  00:23:01,960
That means all of these are just names
450

450

00:23:01,960  -->  00:23:04,667
for a user error really.
451

451

00:23:04,667  -->  00:23:08,320
However, they can be caught individually.
452

452

00:23:08,320  -->  00:23:10,890
So when we go to a user model
453

453

00:23:10,890  -->  00:23:14,540
we can catch user not found error individually,
454

454

00:23:14,540  -->  00:23:15,880
or raise it individually,
455

455

00:23:15,880  -->  00:23:19,460
but it behaves just in the same way as a user error would.
456

456

00:23:19,460  -->  00:23:22,600
I.e. it just has an innate method that takes in a message
457

457

00:23:22,600  -->  00:23:24,733
and sets self message to be that.
458

458

00:23:25,733  -->  00:23:27,360
What that means is later on in our user views
459

459

00:23:27,360  -->  00:23:29,990
we can return e.message,
460

460

00:23:29,990  -->  00:23:33,520
and we know that if we caught a user error
461

461

00:23:33,520  -->  00:23:35,500
or any of its subclasses,
462

462

00:23:35,500  -->  00:23:37,563
it's going to have a message property.
463

463

00:23:40,010  -->  00:23:42,280
Now a couple more things.
464

464

00:23:42,280  -->  00:23:44,550
Here we imported user errors
465

465

00:23:44,550  -->  00:23:47,650
but we never defined user errors.
466

466

00:23:47,650  -->  00:23:49,280
What we're going to do is
467

467

00:23:49,280  -->  00:23:51,510
we're going to change this slightly to say
468

468

00:23:51,510  -->  00:23:56,510
import the entire module as user errors.
469

469

00:23:57,074  -->  00:23:59,930
Don't worry about that warning by the way,
470

470

00:23:59,930  -->  00:24:02,960
what this does is it takes all of these
471

471

00:24:02,960  -->  00:24:05,890
things that are exported by this module,
472

472

00:24:05,890  -->  00:24:07,760
so all of these classes,
473

473

00:24:07,760  -->  00:24:12,720
and essentially puts them inside an object
474

474

00:24:12,720  -->  00:24:15,763
that allows us to access them like this.
475

475

00:24:16,780  -->  00:24:18,840
Python complains saying lowercase variable
476

476

00:24:18,840  -->  00:24:20,300
imported as non-lowercase
477

477

00:24:20,300  -->  00:24:22,440
because we've imported this module
478

478

00:24:22,440  -->  00:24:23,650
and then we've renamed it
479

479

00:24:23,650  -->  00:24:25,460
so that it's no longer all lowercase,
480

480

00:24:25,460  -->  00:24:26,470
now it has uppercase letters,
481

481

00:24:26,470  -->  00:24:29,010
which makes it look a bit like a class.
482

482

00:24:29,010  -->  00:24:30,080
But I think that's okay,
483

483

00:24:30,080  -->  00:24:32,960
you could import it as errors if you prefer,
484

484

00:24:32,960  -->  00:24:34,003
it's up to you.
485

485

00:24:36,490  -->  00:24:40,320
The other problem we've got is in the user's view
486

486

00:24:40,320  -->  00:24:44,773
we've sent from models.user import user and user errors.
487

487

00:24:46,150  -->  00:24:49,310
So this won't work, evidently.
488

488

00:24:49,310  -->  00:24:52,210
Firstly because models.user is a folder
489

489

00:24:52,210  -->  00:24:56,590
it is not a file, so how can you import from it?
490

490

00:24:56,590  -->  00:24:59,660
And you maybe thinking hold on,
491

491

00:24:59,660  -->  00:25:03,800
what we should do here is from models.user.user import user.
492

492

00:25:03,800  -->  00:25:08,000
And from models.user.errors import,
493

493

00:25:08,000  -->  00:25:10,763
oh sorry, like this user errors.
494

494

00:25:11,680  -->  00:25:13,320
There we go, import.
495

495

00:25:13,320  -->  00:25:15,359
Maybe this is what we should be doing?
496

496

00:25:15,359  -->  00:25:16,192
Right?
497

497

00:25:16,192  -->  00:25:20,620
And you are right, that is what you should be doing
498

498

00:25:20,620  -->  00:25:25,320
but you can do this if you copy that
499

499

00:25:25,320  -->  00:25:29,770
and put it in the dunder init.py file.
500

500

00:25:29,770  -->  00:25:31,100
Now you can see the error disappears
501

501

00:25:31,100  -->  00:25:32,280
and Python likes that.
502

502

00:25:32,280  -->  00:25:33,510
Why is that?
503

503

00:25:33,510  -->  00:25:36,040
Because when you import from a package,
504

504

00:25:36,040  -->  00:25:40,497
i.e. a folder that has a dunder init.py file,
505

505

00:25:40,497  -->  00:25:45,497
Python will automatically import from that file.
506

506

00:25:46,520  -->  00:25:50,660
So what we can do is we can use that file as a shortcut.
507

507

00:25:50,660  -->  00:25:54,360
We can import everything that is inside the folder
508

508

00:25:54,360  -->  00:25:57,250
into this init file,
509

509

00:25:57,250  -->  00:25:59,500
and then other parts of our application
510

510

00:25:59,500  -->  00:26:03,440
can just directly import from the folder itself.
511

511

00:26:03,440  -->  00:26:05,380
Just makes the import a little bit cleaner
512

512

00:26:05,380  -->  00:26:06,720
and a little bit simpler.
513

513

00:26:07,670  -->  00:26:10,480
So there's like a small trick for you
514

514

00:26:10,480  -->  00:26:11,780
if you're learning Python.
515

515

00:26:13,510  -->  00:26:16,183
We haven't made use of url for, or redirect use yet,
516

516

00:26:17,056  -->  00:26:18,700
but we will do when we get to logging in,
517

517

00:26:18,700  -->  00:26:22,770
so don't worry too much about the unused methods there.
518

518

00:26:22,770  -->  00:26:26,080
But we are ready now to register users.
519

519

00:26:26,080  -->  00:26:29,310
So let's go ahead and run our app,
520

520

00:26:29,310  -->  00:26:30,460
make sure it's working.
521

521

00:26:31,320  -->  00:26:33,240
Load it up on Chrome,
522

522

00:26:33,240  -->  00:26:37,680
and we're gonna go to users/register
523

523

00:26:37,680  -->  00:26:41,050
and we have here our email and password.
524

524

00:26:41,050  -->  00:26:42,990
Make sure MongoDB is running
525

525

00:26:42,990  -->  00:26:45,985
and then I'm gonna type jose@example.com,
526

526

00:26:45,985  -->  00:26:48,033
password is gonna be one-two-three-four.
527

527

00:26:49,220  -->  00:26:50,053
Sign it up.
528

528

00:26:50,910  -->  00:26:53,454
And we have a problem, our first problem.
529

529

00:26:53,454  -->  00:26:55,700
It says runtime error,
530

530

00:26:55,700  -->  00:26:59,060
this session is unavailable because no secret key was set.
531

531

00:26:59,060  -->  00:27:00,770
Set the secret key on the application
532

532

00:27:00,770  -->  00:27:02,510
to something unique and secret.
533

533

00:27:02,510  -->  00:27:04,350
Okay, that's a pretty nice error.
534

534

00:27:04,350  -->  00:27:06,590
Whenever we use cookies,
535

535

00:27:06,590  -->  00:27:11,330
i.e. whenever we send data from our app into the browser
536

536

00:27:11,330  -->  00:27:14,270
and we want that data to be secure
537

537

00:27:14,270  -->  00:27:17,410
so the users can't change it.
538

538

00:27:17,410  -->  00:27:19,700
For example, if a user has a cookie
539

539

00:27:19,700  -->  00:27:21,800
and it says hey, this cookie is associated
540

540

00:27:21,800  -->  00:27:24,640
with that session in your application,
541

541

00:27:24,640  -->  00:27:26,560
a user could potentially go and change it
542

542

00:27:26,560  -->  00:27:29,370
and associate their cookie with somebody else's session.
543

543

00:27:29,370  -->  00:27:31,466
Essentially accessing somebody else's data.
544

544

00:27:31,466  -->  00:27:36,360
So that is why we want to secure the data
545

545

00:27:36,360  -->  00:27:38,143
when it's stored in a cookie.
546

546

00:27:39,270  -->  00:27:41,900
Flask secures the data by using something
547

547

00:27:41,900  -->  00:27:43,350
called a secret key,
548

548

00:27:43,350  -->  00:27:45,720
but we haven't set a secret key.
549

549

00:27:45,720  -->  00:27:48,210
So we're going to set one just now.
550

550

00:27:48,210  -->  00:27:51,220
Go into app.py, and under app declaration
551

551

00:27:51,220  -->  00:27:56,043
say app.secret key equal os.urandom 64.
552

552

00:27:58,318  -->  00:28:00,343
This will not work on Windows,
553

553

00:28:00,343  -->  00:28:02,730
so this only works on Mac.
554

554

00:28:02,730  -->  00:28:04,140
You do have to import OS.
555

555

00:28:04,140  -->  00:28:06,040
I think it also works on Linux
556

556

00:28:06,040  -->  00:28:08,426
but don't think it'll work on Windows.
557

557

00:28:08,426  -->  00:28:10,510
So if you are using Windows just type in a string here
558

558

00:28:10,510  -->  00:28:12,950
that is long and random.
559

559

00:28:12,950  -->  00:28:14,820
It can be anything you like.
560

560

00:28:14,820  -->  00:28:15,980
For now I'm gonna type
561

561

00:28:15,980  -->  00:28:17,330
app.secretkey = Jose
562

562

00:28:17,330  -->  00:28:19,300
which is neither long or random,
563

563

00:28:19,300  -->  00:28:23,060
so don't use this when we deploy our application.
564

564

00:28:23,060  -->  00:28:24,580
Because if they know the secret key
565

565

00:28:24,580  -->  00:28:28,302
the users can still change the contents of the cookie.
566

566

00:28:28,302  -->  00:28:32,060
So again, if you're using Mac or Linux,
567

567

00:28:32,060  -->  00:28:37,060
os.urandom 64 will generate a 64 character long
568

568

00:28:37,170  -->  00:28:39,270
random, Unicode string,
569

569

00:28:39,270  -->  00:28:43,330
which is a pretty good way of getting something fairly safe.
570

570

00:28:43,330  -->  00:28:46,930
If you're using Windows, do you just a string
571

571

00:28:46,930  -->  00:28:49,204
with letters and numbers and symbols and all that stuff.
572

572

00:28:49,204  -->  00:28:53,593
Okay, we can restart our app and try again.
573

573

00:28:58,050  -->  00:28:58,883
Brilliant.
574

574

00:28:58,883  -->  00:29:01,350
So it says the email used to register already exists
575

575

00:29:02,814  -->  00:29:04,320
because well I'd been testing this earlier on,
576

576

00:29:04,320  -->  00:29:07,673
but I will type bob@example.com,
577

577

00:29:08,940  -->  00:29:11,160
and there we get back the email.
578

578

00:29:11,160  -->  00:29:14,530
So what we saw there was that
579

579

00:29:14,530  -->  00:29:17,650
the user was registered, at first,
580

580

00:29:17,650  -->  00:29:19,600
and that created an error.
581

581

00:29:19,600  -->  00:29:22,428
If we find the user by email
582

582

00:29:22,428  -->  00:29:25,839
this will raise a UserError.UserAlreadyRegisteredError.
583

583

00:29:25,839  -->  00:29:30,508
When that happens it automatically stops execution
584

584

00:29:30,508  -->  00:29:35,473
and jumps over to the caller of this function.
585

585

00:29:35,473  -->  00:29:40,473
Notice that if this was caught here
586

586

00:29:40,800  -->  00:29:43,490
then it would jump to the appropriate except block,
587

587

00:29:43,490  -->  00:29:45,652
but it is not caught.
588

588

00:29:45,652  -->  00:29:47,628
Here we're not catching user not found error,
589

589

00:29:47,628  -->  00:29:49,690
we're not catching user already registered error.
590

590

00:29:49,690  -->  00:29:54,000
So it jumps straight to the caller which is here.
591

591

00:29:54,000  -->  00:29:56,801
And because that error is a subclass of user error
592

592

00:29:56,801  -->  00:30:00,532
we then return e.message.
593

593

00:30:00,532  -->  00:30:04,170
Afterwards we tried with bob@example.com.
594

594

00:30:04,170  -->  00:30:06,960
We registered the user, nothing bad happened,
595

595

00:30:06,960  -->  00:30:09,797
so we set the session's email to be email
596

596

00:30:09,797  -->  00:30:11,663
and then we returned email.
597

597

00:30:13,240  -->  00:30:16,658
What I'm gonna do now is I'm gonna go over to the alerts
598

598

00:30:16,658  -->  00:30:20,730
and I'm going to in the index do something like print,
599

599

00:30:20,730  -->  00:30:23,067
session, email.
600

600

00:30:23,067  -->  00:30:25,823
And I'm going to import session from Flask.
601

601

00:30:28,410  -->  00:30:29,780
Okay, that restarts my app.
602

602

00:30:29,780  -->  00:30:31,740
Do restart it if it doesn't restart.
603

603

00:30:31,740  -->  00:30:34,703
And then we're gonna go over to alerts.
604

604

00:30:35,920  -->  00:30:37,360
Now we get an error.
605

605

00:30:37,360  -->  00:30:39,252
So, what's happening?
606

606

00:30:39,252  -->  00:30:43,350
The error says key error, email.
607

607

00:30:43,350  -->  00:30:46,190
What that means is a very bad way of saying
608

608

00:30:46,190  -->  00:30:50,283
the email key does not exist inside session.
609

609

00:30:51,660  -->  00:30:53,480
But I thought we just set it?
610

610

00:30:53,480  -->  00:30:56,910
We said session email equal email.
611

611

00:30:56,910  -->  00:30:58,513
So why is it now not set?
612

612

00:30:59,530  -->  00:31:02,250
The answer is because we restarted our app
613

613

00:31:02,250  -->  00:31:05,283
and when you restart your app the session gets cleared.
614

614

00:31:06,160  -->  00:31:10,001
So what you wanna do is go back to registering,
615

615

00:31:10,001  -->  00:31:13,100
register a new user,
616

616

00:31:13,100  -->  00:31:18,100
something like rolf35@gmail.com,
617

617

00:31:19,538  -->  00:31:22,450
sign up, make sure that works.
618

618

00:31:22,450  -->  00:31:25,950
And then you can go into your alerts and now it works.
619

619

00:31:25,950  -->  00:31:27,870
And down here you can see that
620

620

00:31:27,870  -->  00:31:30,900
we've printed out rolf35@gmail.com
621

621

00:31:30,900  -->  00:31:33,683
because our alerts prints the session email.
622

622

00:31:34,820  -->  00:31:36,270
Again if you restart your app
623

623

00:31:37,116  -->  00:31:39,484
you will have to sign up with an entirely new email address
624

624

00:31:39,484  -->  00:31:41,813
in order to get session email to be populated.
625

625

00:31:42,830  -->  00:31:44,730
So that is a very common error
626

626

00:31:44,730  -->  00:31:48,470
that you see when something goes wrong during registration
627

627

00:31:48,470  -->  00:31:50,670
and session email is not set.
628

628

00:31:50,670  -->  00:31:53,230
Then when you go and try to access session email
629

629

00:31:53,230  -->  00:31:54,730
somewhere else in your application
630

630

00:31:54,730  -->  00:31:57,210
you're gonna get an error saying hey,
631

631

00:31:57,210  -->  00:31:59,700
you tried to access the email stored in the session,
632

632

00:31:59,700  -->  00:32:03,890
but there is no email stored in the session, so error.
633

633

00:32:03,890  -->  00:32:06,560
We're gonna learn how to deal with those errors
634

634

00:32:06,560  -->  00:32:09,037
more gracefully in the future.
635

635

00:32:09,037  -->  00:32:12,620
And the reason for that is in many places in our application
636

636

00:32:12,620  -->  00:32:15,010
we'll be accessing session email.
637

637

00:32:15,010  -->  00:32:17,746
And what happens if session email is not set?
638

638

00:32:17,746  -->  00:32:22,030
Well it's going to mean that the user is not logged in.
639

639

00:32:22,030  -->  00:32:23,970
It's not the cause for an error,
640

640

00:32:23,970  -->  00:32:27,050
all we have to do is ask the user to log in.
641

641

00:32:27,050  -->  00:32:29,450
So we're going to be dealing with that later on.
642

642

00:32:30,920  -->  00:32:32,920
For now, I hope this video was useful,
643

643

00:32:32,920  -->  00:32:34,610
it's been a bit of a long one
644

644

00:32:34,610  -->  00:32:36,610
and we've had to do quite a lot of work.
645

645

00:32:37,500  -->  00:32:39,710
Create a template for our users
646

646

00:32:39,710  -->  00:32:41,725
to send us an email and a password.
647

647

00:32:41,725  -->  00:32:45,231
Then we've created a user view that takes them in
648

648

00:32:45,231  -->  00:32:47,730
and registers the user.
649

649

00:32:47,730  -->  00:32:50,960
And also it sets the email in the session
650

650

00:32:50,960  -->  00:32:54,460
so that when the user comes back with the same browser
651

651

00:32:54,460  -->  00:32:56,820
and the same Flask app running,
652

652

00:32:56,820  -->  00:32:58,460
we will be able to identify them
653

653

00:32:58,460  -->  00:33:00,533
and populate the session automatically.
654

654

00:33:01,420  -->  00:33:03,840
Registering a user also does a bunch of stuff,
655

655

00:33:03,840  -->  00:33:05,750
it checks the email is valid,
656

656

00:33:05,750  -->  00:33:07,350
or returns an error if it's not.
657

657

00:33:08,250  -->  00:33:11,318
Then it tries to find the user with the given email
658

658

00:33:11,318  -->  00:33:15,010
and if it's not found then this function up here
659

659

00:33:15,010  -->  00:33:17,960
raises an error which we catch.
660

660

00:33:17,960  -->  00:33:19,260
And if the user was not found
661

661

00:33:19,260  -->  00:33:20,630
it means the user does not exist,
662

662

00:33:20,630  -->  00:33:24,000
which means we can create one and send it to MongoDB
663

663

00:33:24,000  -->  00:33:25,050
and then return true.
664

664

00:33:26,450  -->  00:33:28,233
If the user was found,
665

665

00:33:29,660  -->  00:33:32,660
then that means that we want to raise an error saying
666

666

00:33:32,660  -->  00:33:34,370
hey, the user is already registered
667

667

00:33:34,370  -->  00:33:36,120
because we found it in the database
668

668

00:33:37,178  -->  00:33:38,011
so it means it must exist.
669

669

00:33:38,011  -->  00:33:40,550
So we return a message to the user saying
670

670

00:33:40,550  -->  00:33:43,143
the email you used to register already exists.
671

671

00:33:44,806  -->  00:33:46,896
As part of doing this we also coded our models,
672

672

00:33:46,896  -->  00:33:50,000
our user model, and our errors.
673

673

00:33:50,000  -->  00:33:53,470
And of course the utils common package.
674

674

00:33:53,470  -->  00:33:54,710
More things are gonna go in here
675

675

00:33:54,710  -->  00:33:57,240
related to password encryption later on.
676

676

00:33:57,240  -->  00:33:59,030
And we're also gonna add a couple more errors
677

677

00:33:59,030  -->  00:34:00,163
as we go along, too.
678

678

00:34:01,250  -->  00:34:02,830
Thanks for joining me in this video
679

679

00:34:02,830  -->  00:34:04,480
and I'll see you on the next one.
