Adding UI Authorization0:00
Alright, let's wrap up this series by having a look at authorization. So you'll remember a few episodes ago, we added this link to create a new User. But now, let's say, only certain people in the system are authorized to create Users. And the problem is, right now, anyone can create a User, which you may not want. Alright, let's see what we can do. I'm going to return to routes/web.php. And if we scroll down, here's the users endpoint. And let's see, we'll add a new prop here called can. Can you create a User? createUser.
Can you create a User? Create User. And right now, I'm going to hard code it. We'll say false. Nobody can create a User right now. Okay. So now, if I go to my users/index component, we will accept can, which is the authorization. And now, if I scroll all the way to the top where we add a new User, we can now conditionally display this with if can create User. Alright, let's see if it works.
display this with if can create User. Alright, let's see if it works. Come back to Firefox, give it a refresh, and I no longer see that link. Cool. So now, if we go back to the routes file, let's make it a little more dynamic. Let's check if the authenticated User's email happens to be somebody who's the administrator. So I think I'm signed in as Susan, and her email is susan.doe.com. Okay, that's a simple bit of authorization. So now, if I come back and refresh, only on the condition that you have that email will you see this link.
So now, if I come back and refresh, only on the condition that you have that email will you see this link. But if it were somebody else, maybe John, well now, I, as Susan, will not see that link. Perfect. Okay, but now, don't forget, that only gets us half of the way there. Yes, we're not displaying the link, but we're also not protecting the endpoint. Which means, if I try to access users/create, well, we can still create a user, even though that's supposed to be unauthorized. Okay, so now, if I switch back, okay, so how do we do this? Right now, we're sort of hard-coding this logic within the route, but we also want that.
Creating a Policy2:01
Okay, so now, if I switch back, okay, so how do we do this? Right now, we're sort of hard-coding this logic within the route, but we also want that logic to be applied to the accessing of the route itself. In these situations, I like to reach for a policy, like this, php artisan make:policy UserPolicy. And that will be a policy for the User model. Okay, so now, on the sidebar, we will find a new app/Policies directory right here. And there's our first one. Okay, so Laravel gives us a bunch of these actions we can use, but to keep it simple, I'm going to get rid of everything except, how about, just create.
Okay, so Laravel gives us a bunch of these actions we can use, but to keep it simple, I'm going to get rid of everything except, how about, just create. Okay, so now, think about it. I'm just going to grab all of our logic before, paste it in, but this time, rather than checking the authenticated user, we instead receive the current user that Laravel passes for us. So let's check if the user's email address is John Doe. Okay, great. So now we have a policy that we can use in a number of places. First up, we're going to remove this and check if the authenticated user can create a User.
So now we have a policy that we can use in a number of places. First up, we're going to remove this and check if the authenticated user can create a User. And that should do it. So now, if I switch back and refresh, we still don't see it because only John Doe is authorized. Let's bring that back to Susan. And now, she should see it. Okay, great. So now that we've extracted that authorization logic into its own policy, we can now protect this create endpoint in the same way. All right, so we come back, scroll down to where we create a new User, and I'll show
Protecting Routes with Middleware3:42
this create endpoint in the same way. All right, so we come back, scroll down to where we create a new User, and I'll show you two ways to add this. Traditionally, you would use the middleware method, and you would use the can middleware. So can, we create a new User. And because we don't have an existing User record, we provide the class path, App\Models\User. Okay, so now Susan can access this link. But if I bring it back to John, she can't, and she'll get a 403 unauthorized. Okay, this is what we want.
Record-Level Edit Authorization5:09
But if we also conditionally have authorization for each record, then maybe we can add it here. And I'm going to do the same thing. Now, you don't have to wrap this within a can array or object. If you'd rather just say something like creatable or editable, you can do that as well. It really doesn't matter. Just by convention, though, I learned it this way, so it's kind of what I stick to. But there's no real right or wrong here. Okay, so can we edit the given User here? And I'm going to use the exact same logic. Auth user can, and this time I'll call an action edit the given User.
And I'm going to use the exact same logic. Auth user can, and this time I'll call an action edit the given user. Okay, so let's go back to our policy. We had one for create. And now we're going to do another one for edit. Now remember, this is the current user. The second argument would be the user that the current user is editing. So I kind of want to call that user as well, but I'll just stick with model or other user or whatever you want. Okay, so now in this case, it's a demo app.
or whatever you want. Okay, so now in this case, it's a demo app. I don't really have any actual logic. We don't have teams or hierarchy or anything like that. So why don't we just make it random for the demo? So let's return a random number between zero and one, and I'll force that to a Boolean. Okay, but yeah, of course, in real life, remember, according to your app's logic, you would reach for these users to figure out if one can edit the other. Okay, so now if I come back to our users/index component, let's find that edit link. And once again, I will conditionally display it if the current user can edit.
Okay, so now if I come back to our users/index component, let's find that edit link. And once again, I will conditionally display it if the current user can edit. And you can see why I often use that can array or the object. I think it just reads a bit better in your view component. Show this td if the user can edit. And again, just to be crystal clear, we are accessing that here. So for each user, we're going to add can and then edit. All right. So let's come back to Firefox, give this a refresh. And now some of them are turned on and some aren't.
So let's come back to Firefox, give this a refresh. And now some of them are turned on and some aren't. And in this case, because it's dynamic, it'll be different every single time, which is a bit weird, but not a great idea. But you get the idea for the demo. And let's just do this. Okay, so I think we are about done. Oh, yeah, last little thing. You can call the can middleware like this. Or in the latest version of Laravel, you can call a can method directly off of your
Route can() Method7:35
You can call the can middleware like this. Or in the latest version of Laravel, you can call the can method directly off of your route declaration. So that would change to can, create, and then you provide the model name here. But just a little note, if you're working along and that's not working for you, you just need to update Laravel because it was recently added at the time of this recording. So I can just do a quick composer update like that. Now if I come back and give this a refresh, it will work. All right, so I think that's about enough to wrap up this introductory series. But rest assured, if you do want to dig deeper, we will be providing a bunch of content at
Homework: Implement User Edit8:06
All right, so I think that's about enough to wrap up this introductory series. But rest assured, if you do want to dig deeper, we will be providing a bunch of content at LaraCast to help you out. So if you want some homework, right now we added these edit links, but we haven't implemented them. So your job would be to add a new endpoint to edit a User. And if you want some basic ideas on how you would do that, well, think about it. First, you would need to add a new route to edit a User. Next, make sure that you add the necessary authorization. Then you would, of course, create a new Inertia component, so users/edit, where you
Next, make sure that you add the necessary authorization. Then you would, of course, create a new Inertia component, so Users/Edit, where you would add your form. And your form can probably snatch a bunch of this logic here to save yourself a little bit of time. See if you can get that up and running. And if you need any help, of course, ask questions in the comments below. All right, thank you, everybody. I hope you enjoyed it.
