2.5 Login Tickets, Part 2
This is part 2 on implementing login tickets. We'll learn about their role in the login process and test drive their implementation.
1.Introduction2 lessons, 07:43
2.Creating the API Server12 lessons, 2:10:56
3.A Client Demonstration App2 lessons, 20:49
4.Conclusion1 lesson, 01:35
2.5 Login Tickets, Part 2
This is part two on providing login tickets into our application. I want to focus my attention on this specific test. We're given a login ticket here which will spawn anytime we run a new test in this described block. And the test expires a login ticket after an unsuccessful auth attempt. So, anytime we try to login but we are not successful, meaning we pass either a bad user or a bad password with a particular service, we call the service, and the login ticket should not be active. We already have this attribute in the database table. So, we will be able to manipulate it and query for it for our test. So, the log in class expects a set of data. We still don't have that here, but we will. So, the first thing is to the run the tests to see what we should do first. Okay, you can see that the spawn login ticket method doesn't exist. We'll need to create it, because we are using it in line 42. Let's go to the test helper, and inside, we're going to create a similar method to this one. So, spawn login ticket. It doesn't have any arguments whatsoever, because it's not needed. Basically, what we want to do is create a new login ticket, by typing in create and then a name. The name will be something like we already have in the login class. In fact, now that I think of it, why don't we call this service already? Let's do that, instead of repeating ourselves we're going to type in, for example, api, double colon, services, double colon, login, dot, new. We're going to assign this to a service variable, call the service, and finally retrieve the ticket. So, service.ticket. This should do the trick. We are calling the call method and retrieving the ticket. It looks rather good. Let's run the tests and hopefully, that should be out of the way. There you go. Now, you can see that we are only failing one test, not three. We are expecting zero arguments, but we sent one. So, that means that the login class here, as you can see in the test, is expecting four parameters. So, let's define the initialize method here, which will take all of those arguments. So, we'll expect a username which will default to nil, the password as well, so password nil, then the login ticket name. And the reason I'm typing login ticket name is because we are being sent a string and not a login ticket class. And then, the service, which will also default to nil. At the end of it all, we just want to register those variables. So username will be username, so on and so forth. Okay, there you go. Now, you can see that this will affect the overall performance of this class, you know, the whole operation. So, we want to generate a ticket in case there is no user name, for example. So, if username.nil, then we want to generate that ticket. In fact, I'm going to create a new method called generate login ticket. Otherwise, we are going to effectively attempt a login. So, I'll just call it the login method. Okay, so the next step should be to extract this into its own method, which I'm going to call generate login ticket. Let's finish that up, and also, let's create the login method. If we didn't do this, it will throw an error, and we wouldn't be able to proceed. Okay, let's try and run the tests again to see if both tests, the first one and this one, are running smoothly. We only have one failure, and that means that the previous test we handled is still green. We only need to take care of this one. We expected the login ticket to not be active. So, let's take care of that. Well, the first thing is, we need to make sure that the user exists with that password. That means that we need to have some sort of condition that tells us whether the user is authenticated or not. I am going to provide a valid auth method, which will tell us whether the authentication is valid or not. I'll create that method as private. You know, I should really make these two private as well so I'll paste them right below and create the other method called valid_auth and we just need to find the user with that username and the password also matches. So, let's do that. I'm going to type in user.where and then the email should be that username. So, we'll pass username and then the encrypted password should also match. So we'll use encrypted password and then digest double colon sha1.hexdigest with that password. Because we are only trying to digest the password that comes from the form, which is also being used in the sign-up form. So, if we go to the sign up service here, you can see that the only thing that we're passing is a password. For now there's no salt to it or anything. And that's just for educational purposes. Of course, you should totally pass in for example a salt of some sort, but for now, we'll just stick to this. So, let's go back to where we were. We want to find a user that matches that email and encrypted password. We want to make sure that the first item, which is the only one that should come out, exists. We don't need to do anything else. So, if there is no valid authentication, then we should just expire that ticket. So, we'll use expire login ticket, which will effectively turn down that login ticket. We'll create that method really quick. There you go. Then, we'll need to find that login ticket based on the name and expire it. So, we'll use LoginTicket.where, pass in the name which matches our login ticket name, and we're going to update the attribute called active and turn it to false. And that's it. We want to fetch the login ticket which was used in the generate login ticket. It was passed in in the constructor, as you can see in the initialize method. In line eight, there's our ticket. And in line 29, if we don't have a valid authentication, we should expire at that login ticket. So, we'll do that. Let's see if the test now passes. Well, it seems we have a syntax error in line 36. Let's see. Oh, there you go. We should close the parentheses here. Let's run the test again, and see the result. You can see that the update attribute method doesn't exist for the relation object. Well, that's easy to fix. Let's retrieve the first record, and then the update attribute method. Run the tests, and there you go. The test now passes. So, this means that the login ticket will be expired after being subject to authentication. Okay, so that's another test covered. In terms of login tickets, I believe this is good enough. We now need to focus our attention on successfully authenticating.