Building data-driven web apps with Pyramid and SQLAlchemy Transcripts
Chapter: User input and HTML forms
Lecture: Creating a user session (cookies)
0:00 So we've been able to login our user
0:02 and register users, and we're doing this just in the context
0:05 more of demonstrating how to interact with forms
0:08 more than how to do proper user management.
0:11 There's a lot of stuff that we're skippping over
0:13 password resets, welcome emails, all kinds of things
0:16 that you're really going to have to do, we're not doing.
0:19 But I do want to have the ability to have users
0:22 in this web app, and one of the important parts
0:24 is actually, once somebody has logged in or registered
0:27 knowing okay well, on the next request
0:30 who is that, are they logged in again?
0:33 Because HTTP in the web it's stateless, right?
0:35 We have to basically carry a cookie back and forth
0:38 to say here's the logged-in user.
0:41 A new Python file called cookie_auth.
0:46 Now, there's a lot of details here that don't matter too much
0:49 so I'm just going to drop them in here and talk you through them
0:52 and you can take them or create your own mechanism.
0:55 Idea is, we want to create a tamper-proof cookie
0:57 that can live in the user's browser
1:01 potentially across sessions you can set it to time out
1:04 after they close the browser if you wanted.
1:06 This one will live longer
1:07 and we're going to set this when they log in
1:09 and then on every request, if we need to know
1:11 if they're logged in and who they are
1:12 we're going to check it.
1:13 I realized I've put this in the wrong place.
1:15 I want to make a folder, a new category here, called
1:17 I may make it a new subpackage.
1:24 And our cookie_auth is going to go there.
1:26 And I also want to have one other function called try_int
1:35 'cause periodically we have to parse ints
1:38 and it can be really annoying
1:40 to have to do a try except.
1:41 So we'll have text to the str
1:45 it's going to return an optional int.
1:50 So here we'll just bundle this try except up
1:53 and do it all here, so we'll return int with text
1:58 and that didn't work, we're going to return None.
2:00 There's your optional, great
2:02 so we're going to use this in our little cookie_auth thing.
2:05 Alright, now it looks like we have everything in place.
2:10 We're just going to have two functions, set_auth
2:12 give it a request and a user ID
2:14 and it's going to do some hashing
2:17 and then create this, store the ID
2:19 as well as somewhat tamper proof sort of check
2:23 that this ID can't be just changed or played with
2:26 then we're going to say before you send the response back
2:30 call this function add_cookie, okay?
2:32 The hashtext is just going to do a little salty hashy stuff
2:35 again with sha512 and then we're going to be able to ask
2:39 give me the user from the cookie
2:40 and then it'll just look in the request cookie
2:43 pull it apart, make sure some stuff is okay
2:46 and then get the user ID back
2:49 assuming that it hasn't been tampered with.
2:51 Great, so that's all there is to this
2:52 and let's go and use it here.
2:55 So down here we say login user, let's do it.
2:57 We'll say cookie_auth, import that.
3:01 We'll say set_auth, and what does it expect
3:04 it expects the request, and user.id that seems easy.
3:10 Same thing for when we log in down here.
3:13 Good, now how do we know it's working?
3:15 Well, there's a couple things we can do
3:16 but let's go up here to this index one
3:19 and we're going to say user ID.
3:23 Instead of setting auth, we're going to say get
3:27 got to pass in our request here like so
3:29 but we got to name it.
3:30 Remember, we unnamed it, so it didn't complain?
3:32 Now we name it again apparently
3:34 so we'll say if not user ID, let's just do this.
3:37 Let's say user equals user service
3:41 and how about find_user_by_id?
3:46 Again, this should be super easy to write.
3:49 That's an int
3:54 an optional user, and it looks really a lot like that.
3:58 So let's go down here and just borrow that.
4:07 Done, isn't SQLAlchemy a thing of beauty?
4:09 Alright, so we come out here and get our user
4:12 and we'll say if not user, we're going to do a redirect.
4:22 Over to account login, otherwise
4:24 we're just going to say maybe we'll set the user
4:26 and pass it over so we can set the name.
4:30 If we need to do something interesting
4:31 let's go to our index and just say
4:35 welcome to your account, user.name.
4:41 Let's see if that all holds together.
4:44 Right now, we're not sending the cookie.
4:46 We could try to go and do a count.
4:49 And it says no result was found.
4:51 Ah, you know what I want?
4:52 I don't want one for that one, I want first.
4:55 One is, it's going to be an error if it's not there.
4:57 I think I used it before, maybe it was in a place.
5:02 First, I also want that to not crash.
5:05 Sometimes you do want it to crash.
5:06 You're certain you're asking for something
5:09 and it's not there, but this time I don't.
5:11 So notice I try to go to account.
5:13 No, no, you're not logged in.
5:16 Let's try logging you in.
5:18 Okay, let's log me in.
5:20 Oh, how about that?
5:22 We'll click around, click over and register
5:27 and then if we go back, account, Tada!
5:30 Very last thing up here, we have these showing
5:33 it should say maybe go to your account
5:35 and log out instead of register and log in.
5:38 We'll fix that next.