Building Data-Driven Web Apps with Flask and SQLAlchemy Transcripts
Chapter: User input and HTML forms
Lecture: Creating the user

Login or purchase this course to watch this video and the rest of the course contents.
0:00 Well we've almost finished the registration process and our interaction with forms are working really well. But, let's go work on this other bit here.
0:08 Let's actually go and create the user. So let's do this. Let's say the user's going to be our user_service
0:14 remember we're doing lots of stuff with the database and users, so we created our user_service over here. So we can just import that.
0:23 We're going to add a function, not get_user_count but create_user. We're going to have a bunch more things as well
0:28 and we can just pass the values: name, email and password. Now, this doesn't exist yet but, you know what, we can have PyCharm write it for us
0:38 and this can be a string and a string and a string. And let's actually tell it here that it's going to return not a user
0:49 but an optional user. Why optional? Well you'll see in a second. But we definitely want to return some kind of user here.
0:57 That's just the end of the line, okay. Cool, cool, okay. So what we need to do here is we should also do some validation on name and email and so on
1:05 but we're doing that at the top as well. Let's just trust it for the moment but in a real site we would add that. So how do we do this?
1:11 We're going to create a user, like so. And we're going to set some values. Now, be super, super careful here. Do you do this? Maybe? No.
1:25 Bad, bad, don't do that. You never, ever, ever want to store your password directly in the database.
1:32 It's such a bad idea to store the password in plain text. If for some reason you have a SQL injection attack or your database gets lost, or whatever
1:41 all sorts of bad things are going to happen. So we never, ever, ever want to do this. So instead, let me show you how we're going to
1:46 handle passwords in our app. So come over here, and let's check out this thing called passlib.
1:51 This is one of my favorite of all time modules for Python because it just takes this tricky problem and makes it super, super nice.
1:59 So the way that it works is this thing will go you can import it and it will go and hash up some kind of thing like, I don't know, a password.
2:08 And then it will verify it. Now, of course you could use MD5 or SHA512 or whatever but this does a lot more. It also creates random salt, that is like
2:18 words that are mixed in with the password. And it folds it many, many times. Now what I mean by that, instead of just taking the value and hashing it
2:26 it takes that result and hashes it again and then it hashes it again and hashes it again like 150,000 times.
2:33 So this is a much, much harder to break password if for some reason someone were able to access your database
2:39 and get a hold of the emails and the passwords. So this is pretty easy for us to use. We have to add passlib to our requirements down here like so.
2:55 Make sure those get installed. So this is all good and then up here at the top we need to go and import some stuff. But we're going to go over here
3:02 and we're going to say from passlib.handlers.sha2_crypt import sha512_crypt as crypto We're going to import SHA512 and let's do this as crypto.
3:17 That way when we use it below if for some reason we decide we want to change our handler or something we can do that pretty easily.
3:23 So now I'm just going to drop two functions down here. One is to do the hashing and one is to do the verification. Okay?
3:29 So we have hash.txt, which takes plain text and encrypts it and we're setting the rounds to be something kind of random but really high.
3:36 171,204 iterations, that's going to make it extremely computationally challenging to break. And then we want to go and verify it.
3:46 You can't directly compare these because each encryption result results in using random salt but once one of these strings exists
3:54 it knows how to verify it. So what we're going to do here is just a super simple hash.txt and give it the password. There we go. That's much better.
4:02 And now we're going to need one of these sessions, like so. I'm going to say session.commit when we're done and we're going to return the user.
4:10 All right, and then before we actually call commit we need to do session.add, remember that? And that'll add it here. Now, this all looks pretty good.
4:18 There's one other issue, we may have a problem here. So let's just write one more function and you'll see why. Def find_user_by_email.
4:33 And it's going to do something super simple but it's going to come down here and say return session of query. And so what we're going to do is find
4:41 and see if somebody's already registered with this email address because that would be bad to re-register them, right?
4:54 All right, so that's going to just give us the one user back and let's say if find_user_by_email this email address, return None.
5:06 So we don't want to create the user otherwise this user has not registered with us yet we're going to create their account
5:12 we're going to set their values, hash their password put them in the database, commit it and return it. Phew, all right.
5:19 So that seems like a lot, but I think we're good. Let's do a quick test, if not user that meant we couldn't create it.
5:24 Let's do something like this. Here we go. So if for some reason the thing already exists we're going to bail, otherwise we'll redirect.
5:34 Let's go and actually do a quick query, look in our database and see if this user already exists, or not. It shouldn't exist. Go here.
5:45 Say select star from users. What your email is, michael@talkpython.fm. We run that, look, zero rows.
5:55 All right, now, now let's go try to run this, here. Make sure everything's working, good, good. Now let's go try to register again.
6:04 So I'm going to be Michael. Right, here we go. It should go through, actually let's not put the password yet. Some fields are missing.
6:16 Let's go and try to register. Boom, it went through. It didn't crash. All of these are really good signs.
6:23 Let's go to the database and ask that question again. Look at that, user 85 is now registered. Michael, michael@talkPython. Here's that crazy password.
6:33 Like, that's really not very much at all like what I typed, right? That's not the letter a. Down here we have our logins, our created_date
6:41 we didn't set the profile image, that's all fine. Let's do one more test. Let's go back and try to register again.
6:46 I'm Jeff. And my email address is that. Let's try again. A user with that email already exists. Okay, great, I think our forms
6:56 and our user interaction is pretty good. At least on the registration level.


Talk Python's Mastodon Michael Kennedy's Mastodon