تماشای این درس نیاز به اشتراک حرفه‌ای دارد.

مرور اعمال مجوزهای دقیق0:00

The really nice thing about token abilities is that we can use them practically anywhere that we need to check permissions, and it allows us to do some pretty granular checks. For example, the update method is where a User would update a Ticket, and a typical User should be able to update only their own Tickets. But we can also limit what they can update, like the title, the description, the status. That should be it. They shouldn't be able to change the author_id that was assigned to their Ticket. So one of the ways that we could do that is, well, right here for this mappedAttributes. Now if you'll remember, the mappedAttributes takes the data from the request and maps that to the actual attributes on our Ticket model.

Now if you'll remember, the mapped attributes takes the data from the request and maps that to the actual attributes on our Ticket model. So if a User submitted the title and then the authorId, this map would create an array that has the title and its value, the userId and its value, and then those things would be updated. So for a User that shouldn't be able to do that, you know, they would have that updateOwnTicket ability, we could just drop that out of the map, and we could do something like this. If the User does not have a token that can updateOwnTicket, then we will add that mapping back in.

If the user does not have a token that can update own ticket, then we will add that mapping back in. So we will have our attribute map for the author_id, and we will map that to the user_id. And, you know, that would work for the update requests, but it would also cause some issues with our other requests. Because this mapAttributes method is used inside of not just update, but the store method, the replace method. I mean, any place that we need to work with that request data, we are using this mapped attributes.

I mean, any place that we need to work with that request data, we are using this mapped attributes. So that really isn't going to work unless if we add other conditions, like if we check if the route is, and then, you know, have some other things there, and I don't necessarily want to do that. And there's another problem here as well, because let's assume, once again, that the client submits a request to update the title and the author ID. So if we drop out the author ID, and just update the ticket, well, we're still processing that request. We still change the title, they see that with the response, and that's really not something

Validate Author ID Updates2:24

that request. We still change the title, they see that with the response, and that's really not something that I want to do, because it's really an invalid request. If they supplied the authorId, and we're not supposed to allow that, then we should tell them, hey, this isn't a valid request. So doing that here inside of mappedAttributes really isn't the best place to do that. Instead, well, we should go to the UpdateTicketRequest, because this is the class for handling the validation for update requests. And this is going to be a real simple change. We can leave our rules as is, but we will still check to see if the user has a token.

And this is going to be a real simple change. We can leave our rules as is, but we will still check to see if the user has a token that can update own ticket. And if so, then we are going to change the rule for the author ID. We will simply say that it is prohibited. And that's going to be perfect. That is going to prevent clients from submitting a request that includes the author ID. And of course, that's only for clients that have the update own ticket ability. So then that forces them to submit requests that only have the title, description, status. And yeah, I think that that's going to work.

Avoid Wildcard Abilities3:32

So then that forces them to submit requests that only have the title description status. And yeah, I think that that's going to work. Now, there is a caveat here, because we can assign an ability of an *. And if we do that, then that token can do every ability whatsoever. So like for an admin, we might be tempted to assign this * of an ability, in which case this would be true, because for all intents and purposes, that admin User would have the updateOwnTicket ability. And so, yeah, we kind of need to be aware of that. So let's do this. Inside of abilities, inside of our getAbilities, we'll say don't assign an *.

So let's do this. Inside of abilities, inside of our getAbilities, we'll say don't assign an asterisk. That way, you know, that's just a little note to us that, you know, this could cause some problems. So we'll just leave that as is. But otherwise, I like this approach. We'll leave that alone. So that should work. And so now I want to turn our attention to the store method, because we broke it. And I think we broke it whenever we implemented this mappedAttributes method.

Fix Store Request Rules4:32

And so now I want to turn our attention to the store method, because we broke it. And I think we broke it whenever we implemented this mappedAttributes method. So this means we need to go to our StoreTicketRequest. And we need to make a few changes for our rules here. I want to change this so that we have a default rule for the authorId. Now, I know that we use the StoreTicketRequest, not just in the TicketController, but in the AuthTicketController. And we will need to address that. But let's focus on this, make sure that this works first. Then we can work on the other controller there.

But let's focus on this, make sure that this works first. Then we can work on the other controller there. So what I want to do is have a default rule for the authorId. So we're going to say that it is going to be required. It is an integer. And we could go ahead and we could use the exists rule. So that we could check to see inside of the users table, the ID column. And that's going to allow us to get rid of this line of code here, where we check to see if that user exists. So we can get rid of that.

where we check to see if that User exists. So we can get rid of that. And then we can go back to our request class. We still want to check the route, because we need to do different things for the TicketsController and the AuthTicketsController. But what I want to do here is we'll check if the User has a token that can create ticket. In which case, we are going to modify that rule. We are simply going to tack on the size constraint. And we will concatenate that with, let's do this. Well, we'll have a variable called user and we'll get its ID.

And we will concatenate that with, let's do this. Well, we'll have a variable called user and we'll get its ID. So let's create that variable $variable equals this $user. So that means we can use that variable here when we call token_can, and then we can use that there. Okay, so if the user has the ability to create a ticket, then we are basically saying that the author_id needs to match the ID of the logged in user. However, remember that this createTicket is a generic ability. This was used not just by a typical user, but it's also being used by a Manager. And in hindsight, I probably should have named these a little bit different,

Add CreateOwnTicket Ability6:41

This was used not just by a typical User, but it's also being used by a Manager. And in hindsight, I probably should have named these a little bit different, like managerCreateTicket or something like that. But here's what we'll do. We'll create another ability called createOwnTicket. And we will assign that to a typical User. So that a typical User will have createOwnTicket, updateOwnTicket, deleteOwnTicket. That means that here we can check if the ability is to createOwnTicket, we make sure that the authorId is the same as the signed in userId, and we're good to go there.

Update Policy and Authorization7:13

we make sure that the authorId is the same as the signed in usersId, and we're good to go there. But that does mean we need to update our policy because now we have this new ability. So let's go to our TicketsPolicy. Let's go to the store method. And there's actually a few things we need to do. We need to get rid of the ticket parameter because that's not needed here. We don't have a ticket to work with. And then here we will simply return can the user create a ticket or can the user create own ticket?

And then here we will simply return can the User create a Ticket or can the User create own Ticket? That should work. We should be good as far as that policy is concerned. So let's go back to our TicketController. So we check our policy, which this also needs to be different. Because if we were using the authorize method, what we would do in this case is pass store, the name of the policy that we want to check. And then we would say the Ticket class.

the name of the policy that we want to check. And then we would say the Ticket class. So we essentially need to do the same thing here. So that we specify the policy, specify our model class. And that should work. So we are checking our policy. Then we need to create the ticket. So we will call ticket::create. We will pass in our mapped attributes. And that should work.

We will pass in our mapped attributes. And that should work. But now we don't need to catch the model not found exception. Now we need to catch the authorization exception. Because the model not found is being handled inside of our validation rules. So we're good to go there. This is so much cleaner than it was. And I'm liking it. So now we just need to check and make sure that all of this stuff works. So let's go to Postman.

Test Changes in Postman8:44

So now we just need to check and make sure that all of this stuff works. So let's go to Postman. And the first thing we need to do is log out. Because we now have that new ability. So we need to sign out and sign back in to get our new ability. But we do need to make sure that the email address is not the manager. So we will get our token here. We will go to our environments, globals. We will change the value of our token. Save that.

We will change the value of our token. Save that. So that then we can make our requests. So let's first of all test the PATCH request. So if I remember correctly, a Ticket with an ID of one is not this user's Ticket. So if we try to change this, we should get... Yep, you are not authorized. Perfect. So let's try that with an ID of two. Because I think that is our ticket.

So let's try that with an ID of 2. Because I think that is our ticket. Let's put this on hold. So we will send that. Yep, that worked. Let's make sure though. Let's change it to see. Sure enough, that changed. Okay, so we are good as far as that is concerned. Now we need to create a ticket.

Okay, so we are good as far as that is concerned. Now we need to create a Ticket. So we have the attributes, title, all that stuff. We have the relationships. Let's do a couple of tests first. Let's try for a User that does not exist. So an ID of 1000. We should get two errors here. We can see that the ID is invalid. And that's because there wasn't a User with that ID.

We can see that the ID is invalid. And that's because there wasn't a User with that ID. But then we can see that the field must be one. And I love that. Because that's going to tell clients, hey, this is the value that you need to supply. So that's great. Let's try with a User that does exist. And we should see something similar. Except that, of course, the User exists. So we only get one error.

Except that, of course, the User exists. So we only get one error. And it says that the field must be one. So great. So let's change that to one. We submit it. And sure enough, we've created a new Ticket. And that's awesome. That is working just fine. So I don't think we broke anything else as far as our TicketController is concerned.

That is working just fine. So I don't think we broke anything else as far as our TicketController is concerned. Our show method works, I think, the last time that it worked. So we probably didn't break anything. The update method, we know that that works. So we're good there. Replace, we shouldn't have broken anything. Destroy, we shouldn't have broken anything. As far as our TicketController is concerned, I think we're done. And we need to focus on the AuthorTicketController so that we can get that working.

As far as our TicketController is concerned, I think we're done. And we need to focus on the AuthorTicketController so that we can get that working. And we will do that in the next episode.

دوست دارید گاهی خبرهای Laracasts را ایمیل کنیم؟