RESTful and HTTP APIs in Pyramid Transcripts
Chapter: Authenticated services
Lecture: Setting up users
0:01 In this chapter, we're going to add a type of authentication that is super common among APIs.
0:07 Basically what we're going to do is we're going to pass an API key along with our client to send this data over basically to show who we are
0:16 maybe this is just because we don't want to have a public API that anyone can use for free or just out in the open
0:22 we want to be able to track who's doing what; maybe the actions are actually modifying things on behalf of a user
0:28 think of github, if you say create a new repository and you pass an API key, right whose account is that going to be created in— yours, right.
0:37 So we're going to talk about those types of things in this chapter. Now, let's start right away with a demo,
0:43 so what we're going to need in order to get started is, unless we just want to have one API key for the entire thing,
0:50 which doesn't make any sense, is we're going to need users, so let's go and add another sequel alchemy type here
0:56 and I'll call this user, and we're just going to have a class called user and it's going to derive from sqlalchemy base as we've just learned, like so.
1:06 Now let's give this— let's go and explicitly set the table name first before I forget, then let' go ahead and give it an id
1:16 and we are not really going to do much with the id it's just going to be autoincrementing, so we'll have a column,
1:23 we can import that from sqlalchemy, and it's going to be an integer we can import that, and it's going to be a primary key,
1:32 and it's going to be autoincrementing true. So here's a nice simple autoincerementing id and let's also go and record when these users were created,
1:40 like whenever I have accounts and account behavior, like a little tiny bit of auditing, always good; so we'll go and create a datetime, call him here
1:51 and we'll set the default to datetime.now. Remember, don't call the function, pass the function. Ok, so now we get into interesting things,
2:01 we probably need a username or an email, often those are actually the same thing in the database, email is name, same thing.
2:07 So let's have this be a string from sqlalchemy, let's say that it's nullable, it's false so that we require it, it has to be unique,
2:17 and we want to be able to index it, we want it indexed, so we can query it, if this is the way you log in with your name
2:25 then obviously we would like to have that unique, we can't have multiple users. We're also going to have a password and it needs to be super explicit,
2:34 this will be hashed password, and we don't need any indexes, or anything that, technically it doesn't have to be unique
2:40 although you kind of hope it is, so remember never, ever, ever, store plain text passwords you always hash it, use something like passlib
2:49 working with this is really out of the scope of this project, this course, but if you are going to have a password, hash it and use passlib.
2:56 Okay, now we get to an interesting thing that we're actually after, the API key, so in here, it's conceivable that we'll have many API keys
3:04 and you can expire them and give them different privileges and whatnot, in our world, things are simple a user has a single API key, alright,
3:11 and you guys can extrapolate the data model if you want to do something more adventurous.
3:16 So here what we're going to say is the API key, it has to be a string, let's go ahead and have it automatically generated,
3:24 so when an account is created that it's just going to automatically be there
3:28 they might not know about it, but if they go and look in their little section
3:31 and their user account if we had one, it would say your API key is such and such. So let's set this to be a function that we're going to call,
3:37 an empty lambda that's going to return a string representation of uuid4 alright, so that's a decent key there, and we also probably want an index
3:50 because when our API call comes in, the thing we're going to be given is the key
3:55 and we need to get the user, so we absolutely want to have this index = true. Okay, I think that's going to be solid for our code here,
4:03 I suppose one other thing we could add although the way we're generating it it's not a problem, but this is also like an effective user name,
4:12 so let's go ahead and set this to be unique, although it's going to be kind of funky to get that generated,
4:17 there's no reasonable chance of that being duplicated, but maybe somebody copies a value from somewhere
4:23 and tries to set it somewhere else, so a little bit of protection there as well.
4:26 Now, let's look at our database, and in this one we don't have our data so we have car, and we have some management details there,
4:35 let's go and rerun this, and then refresh this. Now, notice there's no user, sadly and for whatever reason
4:48 the system is just not pulling this in, it hasn't been pulled in yet, we could start using it other places and it would probably be ok
4:55 but let's just do this, let's be really explicit here, let's just say import, so we'll just import the user here.
5:02 Now, we're not going to use it in any way, but this will before we call this function here, we'll sort of show sqlalchemy base the user class.
5:11 So if we try again, we refresh, magically there's our user, with everything we need.
5:16 Ok, so we have our user, let's go and write one quick query over in our repository, so we are going to be doing a bunch of stuff,
5:25 and down here, we'll ave a class method and let's say what we want to do is get, I'm going to call it something like that,
5:32 find user my api key, it's just going to take an API key, we could even tell them hey this is a string and it returns a user if that's what we want.
5:44 Ok, so then just like before, standard stuff, so we're going to come over here, create a session and then the session is going to be a query of user
5:52 and the filter is going to be user.api_key == api_key alright, this is why we need that index, right, so that's good and this will be a user
6:04 and let's say session.close and then just return user and because we're using first, if there's no user with that API key
6:12 like some of these are passing nothing or they are passing an incorrect one or whatever,
6:16 it's just going to return none, which is pretty decent representation of no user. Okay, now we have this in place, the next thing we have to address is
6:27 how do we pass the data from client to server.