Database Setup and Migration0:00
Laravel 5.1 now includes some ACL capabilities straight out of the box. Let me demonstrate that for you using a little example here. First though, let's go to my database.php configuration file, and we're just going to set up a couple migrations here. So I will use SQLite, and we do need a database.sqlite file. So I will touch storage/database.sqlite, and we have that. Next, let's make a quick migration just so we have some kind of model to demonstrate. We'll just use the typical Post. Create a posts table, and the table we are creating is called posts. All right, so if we take a look at that, create posts, well, why don't we just say an integer for the user_id. That should be positive. And next, let's see, we'll have a title, and then for the body, that will be a full text field. All right, that looks good to me, so let's go ahead and migrate the database. Cool. Next, I forgot to add a model in that process,
Model Factory Test Data0:49
and then for the body, that will be a full text field. All right, that looks good to me, so let's go ahead and migrate the database. Cool. Next, I forgot to add a model in that process, so let's do that now. And then finally, to have some test data, I will open up my database/factories folder. You may know this is new in Laravel 5.1. And let's create a new blueprint, so to speak, for a Post, and that will have, what, a title, a body, and then also the user_id who created the Post. And for that, I'll just create a User, like so, and fetch the id field. All right, so a Post consists of the user_id who created it, a title, as well as the body, and let's be sure to update the body to a paragraph and the title to a sentence, and that looks good to me. Okay, cool, so check this out. If I go ahead and run php artisan tinker, I could say factory for a Post, and let's create one. Okay, so now we have a dummy Post,
Controller and Routes Setup1:38
and that looks good to me. Okay, cool, so check this out. If I go ahead and run php artisan tinker, I could say factory for a Post, and let's create one. Okay, so now we have a dummy Post, and we also have a User as well. Now, we want to add some authorization to ensure that, for example, when creating a Post, only Anthony has that right, at least for the scope of this application. Okay, so let's set up a controller. PostController with a plain stub is fine. And then in my routes.php file, we'll say, route, when you make a GET request, well, you know what, we may use a few options here. So let's set up a full resource. Great. Now, within PostController, well, let's just start with the show view, mostly just so we have an easy way to demonstrate this. For the time being, we'll say, even to view a Post, well, you must be authorized. All right, how do we do that? Now, to begin, we'll just assume we have an auto incrementing ID here,
Defining Gate Authorization2:31
For the time being, we'll say, even to view a Post, well, you must be authorized. All right, how do we do that? Now, to begin, we'll just assume we have an auto incrementing ID here, that's fine for this example. And then we'll say Post::findOrFail($id). And we'll save that here. And then finally, before we return a view, let's just return the title of the post as an example. And by the way, I will import that at the top. Okay, so if we hit this URI in the browser, post/1, sure enough, we get the title of the post. Okay, so now let's get to the ACL stuff. We've decided for this little example, well, to even view a Post, you must be authorized. And in order to be authorized, you must have created the post. Here's how we do that. If we go to app/Providers/AuthServiceProvider.php, you'll see this boot section down here. Now to start, this is one place that you can register your policies. Notice we have this Gate contract here.
go to app/Providers, AuthServiceProvider, you'll see this boot section down here. Now to start, this is one place that you can register your policies. Notice we have this Gate contract here. So we could define something as simple as showPost. This is an identifier, it can be anything you want. If you want to use this convention, that's cool too. Okay, so we'll make this equal to a closure that will accept the currently authenticated User. Or if they're not logged in, it will automatically return false. So you can rest assured that you will have a User. And then finally, we'll have the Post that we will eventually pass through. I'll show you that in a second. Okay, so how could we make sure that the current User has proper permission to view this Post? Well, to start, we could just say, does the currently authenticated User's id equal the user_id associated with the Post? Okay, so now that
proper permission to view this post? Well, to start, we could just say, does the currently authenticated user's ID equal the user ID associated with the post? Okay, so now that we've added this, we can switch back. And you'll see that we have a new Gate facade in Laravel. Or once again, we can reference the contract if you'd prefer. We'll start with this one. And then later, I'll show you the other option if you prefer. So let's go ahead and use Gate at the top. So now we could say Gate::allows or Gate::denies. And as you can expect, one is the opposite of the other. So for example, I could say showPost and pass that in. Well, if the gate does not allow them through, it denies them. Then in that case, I could redirect or simply abort. All right, let's try this out. So if we give it a refresh, sure enough, sorry, not sorry, we do not have permission to access this page. Okay, but now let's simulate that we do.
All right, let's try this out. So if we give it a refresh, sure enough, sorry, not sorry, we do not have permission to access this page. Okay, but now let's simulate that we do. So temporarily, I will say auth login using id 1. Remember, this Post is created by that User with an id of 1. So I'm just simulating this and saying, go ahead and log in the User with an id of 1, which means they do have permission. So we should never hit this block of code, and instead, we display the title. All right, let's run it. And there we go. We're signed in so we can see it. But if they don't, or they are a guest, let me really quick log out just to be sure. Once again, you're not signed in, so you don't have permission to see this page. All right, cool. Let me show you a couple other things here. For example, yeah, you could do this. Or sometimes it's useful to add an owns method to your User object. So for example, you could say
Alternative Authorization Methods5:39
cool. Let me show you a couple other things here. For example, yeah, you could do this. Or sometimes it's useful to add an owns method to your User object. So for example, you could say user owns post, and that can be a little more readable. Okay, let's go down here. And we'll say owns the relationship or the related model. And we can simply check to see if the ID of the user equals the user_id of the relationship. Okay, now, we should get the same thing. But again, if we add this section right here, we are authenticated and authorized. So we see the post. Now, another variant of this would be, well, if you don't want to add this to your methods, there also is an authorized method. And you'll see it if I go to my Controller here. This new trait in Laravel 5.1 authorizes requests. So if we take a look at that, you'll see that we have this authorized method. And it basically does a similar thing here.
This new trait in Laravel 5.1 authorizes requests. So if we take a look at that, you'll see that we have this authorized method. And it basically does a similar thing here. So let's try that one out. Now, I will say this authorize to show the Post. And remember, we have to pass through the post in question here. All right, so let's give it another shot. And it works. Let's try changing it though off logout. Or in fact, why don't we do this really quickly php artisan tinker, and I will make a second User. All right, great. So now I can just log in a different User who is not authorized to view this Post. And if we give it another shot, yep, we're back to where we were before. This action is unauthorized. So yeah, that can definitely be useful in cases where with a single line of code, you can authorize the request. Now let's switch over to Blade and
Blade Authorization Directives7:21
This action is unauthorized. So yeah, that can definitely be useful in cases where with a single line of code, you can authorize the request. Now let's switch over to Blade and view a couple other things. Because really, in real life, anyone should be able to view a Post. So let's not authorize at that point. And instead, I will show a Post and pass through the post in question. And then within a split here, let's create resources/views/posts/show.blade.php. I'll just add a bunch of HTML here, where within an h1, we spit out the title of the post. All right, so if I go back to Chrome, sure enough, we should see the title. But now let's say if you are authorized to update the post, we want to add a link here or a button. Okay, so we would say something like update this post. But we only want this to be visible, once again, if you're authorized. Well, in Blade, you have this new can keyword. And once again,
Okay, so we would say something like update this Post. But we only want this to be visible, once again, if you're authorized. Well, in Blade, you have this new can keyword. And once again, we've referenced the same thing. So showPost, that's not overly appropriate anymore. So let's go back to our ServiceProvider. And we'll say, well, if you can update the post, really, that's what we're checking here. Okay, so let's go back. And we can say if the currentUser can update the post, and we'll pass that through, only on that condition should we display this link. Pretty nice, right? Let's go back to Chrome, give it a refresh. And we don't see it because we're not authorized. But if we simulate this, log in the user with an ID of one, give it a refresh, they are authorized, so we see the link. Now, if I switch back, just as I was showing you that we can call an authorized method, or we could say Gate::allows or Gate::denies, and then we've
they are authorized, so we see the link. Now, if I switch back, just as I was showing you that we can call an authorized method, or we could say Gate::allows or Gate::denies, and then we've referenced the key, we've also learned that we could do it directly within our view using this can keyword. Well, as it turns out, you can also access a can method or a cannot method on your User model. So for example, I could say something along the lines of auth()->user()->can('update', $post). That would work as well. Let's just try this out. If they can update the post, we will return, you can update this, just as a proof of concept. So let's try that out. And I can either reference the auth function here, or of course, import the facade. Anyways, when we run this, we should see, yep, you can update this. But again, if we were not authorized, we wouldn't be able to do this. So that's good to know. On your User instance, and this is basically the equivalent of doing this,
yep, you can update this. But again, if we were not authorized, we wouldn't be able to do this. So that's good to know. On your User instance, and this is basically the equivalent of doing this, you can access in Laravel 5.1, a can method or a cannot method. And don't forget on that note, for example, when you are posting, maybe you have a store method to add a new Post. Well, you can always access the User instance directly off of the request. So you could say $request->user()->can('update', $post), and you can do things like that. It's good to know that you have a few different options here. Alright, so you know what, why don't we call it a day for this lesson. But in the next part, we'll talk about how you can do authorization directly from your form request classes and how you can still reference the Gate facade there, of course. And then we will also review Policy objects. So remember, in closing for this lesson,
classes and how you can still reference the Gate facade there, of course. And then we will also review Policy objects. So remember, in closing for this lesson, here are your steps. Within your AuthServiceProvider, you can define rules and or restrictions for performing certain actions like updating a Post. Then within your controller, you can reference your Gate facade, or the contract as we reviewed. And you can say, well, if we are not allowed to do that particular task, then in that case, I want to redirect them or abort or anything of that nature. Finally, within your views, if you need to perform some kind of authorization, you can now reference this new can directive. Alright, so play around with this stuff. And when you're ready, we'll take it another step further.
