Reviewing Teams Feature0:00
Okay, let's take a look at Teams. We've already taken a look at some of the features of Teams throughout the videos, but let's review. So if you have the Teams feature enabled, then every new User created within the system belongs to at least one team, which is their personal team. So if you go into the example I have here, and if you go to the menu here, you'll see I have my personal team here. Now if you go to Team Settings, then you can invite other existing users here, just add their email address. And you can also assign roles to them, which have associated permissions.
Defining Roles and Permissions0:31
add their email address. And you can also assign roles to them, which have associated permissions. So I also showed you this in the last video. So the roles are defined in JetstreamServiceProvider, right here. And you can assign any permissions you want. And they are just strings. So you can see we have admin and editor here. And the only difference is that the editor cannot delete. So if I wanted to create a new role here, then you can just duplicate this and assign any permissions you want here.
So if I wanted to create a new Role here, then you can just duplicate this and assign any permissions you want here. So I'll just give it a name here. I can't think of a good name right now, so I'll just say anything. And you can give them permissions here. And the permissions are going to merge together. So if they're duplicated, then there will only be one. So since these are the same, there will only be one read permission. Or if you want, you can sort of namespace these, say postUpdate, and that will create a new one.
Or if you want, you can sort of namespace these, say Post update, and that will create a new one. So if I save this, you'll see, let me just change this as well. You'll see this new role in here. But we'll just stick to whatever the default here. So let me just undo this. And if you saw here, I already have a User associated with this Team. And let me just go through the example I have here before we get into the example app. So I have a seeder here. So everything's set up when I migrate the database.
Seeder and Data Setup1:56
So I have a seeder here. So everything's set up when I migrate the database. So I have four Users and two Teams. Actually, no, I have four Users and four Teams because every User has a Team. But only two of those Teams have more than one User. So User A is Andre. This is Andre's personal Team. User B is Will, Will's personal Team. And then I added Will to Andre's Team. User C is Sally, Sally's personal Team, Jen, Jen's personal Team.
And then I added Will to Andre's team. User C is Sally, Sally's personal team, Jen, Jen's personal team. And I added Jen to Sally's team. And I also have posts here, which is the example we'll be looking at. So I post from Andre and a post from Sally. So before we get into this example, we also took a look at actions. And there are a few actions associated with teams. If you go into the actions folder and Jetstream, you'll see some actions for the different functionality of teams, for example, adding a new team member. And the example we had here was I just log this information here.
Introducing Posts Example App2:53
functionality of teams, for example, adding a new team member. And the example we had here was I just log this information here. But say, for example, you wanted to send an email, you can put that in here. Okay. Let's go ahead and take a look at the example I have set up here. So let's go to my routes file here. And you'll see a bunch of routes for posts. And the example I have here is a typical blog application. So if you go into posts here, you'll see the two posts that I have set up in my seeders, one by Andre and one by Sally.
So if you go into posts here, you'll see the two posts that I have set up in my seeders, one by Andre and one by Sally. And listing the posts and reading the posts are both public. And you can see that here in the routes, they are not wrapped in any middleware, but everything else is within middleware where the user has to be logged in. So in order to create, edit or delete posts, you have to be logged in. And I also have other permissions set up as well, which I'll show you. So right now I'm logged in as Andre. So Andre created this post. So Andre can edit this post and Andre can delete this post.
So Andre created this Post. So Andre can edit this Post and Andre can delete this Post. So I can edit if I want, changed, and that should work and it does. And delete works as well, but I won't delete it for now. So if I were to go to Sally's Post, then I should not be able to edit or delete because that is not my Post. And as you see, there is no create or edit button here. So let me show you the PostController that has all that functionality. So index is just grabbing all the posts and showing the view. Creating is just showing the view for creating a new Post.
So index is just grabbing all the Posts and showing the view. creating is just showing the view for creating a new Post. storing is actually storing that new Post and showing is public as well. But for editing, here is the permission that checks whether or not that User can edit that Post. So it's just checking if the User is the one who created the Post. So you can put this in a policy as well, which is what I usually do, but I just put it in the controller here so it's easier to see. And the same permission exists here in the update method and also the delete method here or destroy.
Goal: Team-Based Post Access5:03
And the same permission exists here in the update method and also the delete method here or destroy. So now we want to modify this app so that anyone on the team can edit or delete posts. So like I said, I have Andre and Will on one team. So I want Andre to be able to edit, or sorry, I want Will to be able to edit Andre's posts or delete Andre's posts. So let me log in as Will and obviously the way it's set up now, Will cannot do any of those things. So let me just log out and log in as Will. Okay, so I am logged in as Will and if I go to posts, you'll see that Andre or Will cannot
So let me just log out and log in as Will. Okay, so I am logged in as Will and if I go to posts, you'll see that Andre or Will cannot edit or delete Andre's posts. Oh yeah, one more thing I forgot to show you is the show Blade where the buttons show up. I have the check here as well and I have separate ones for edit and delete. Right now they're the same, but they're going to be different later on. So only show the buttons if the logged in user is the person who created the post. And in this case, Will did not create this post, so it's not showing the buttons. But like I said, Will is a part of Andre's team, so I want Will to have that functionality. So again, depending on your app, you have different use cases for who can see what or
Adding Team ID to Posts6:17
But like I said, Will is a part of Andre's team, so I want Will to have that functionality. So again, depending on your app, you have different use cases for who can see what or who can do what. For example, in the documentation, they mention a calendar app here. So obviously reading is going to be different depending on what User you're signed in as or what team you're signed in as, I mean. So let's go ahead and make this work pretty straightforward. In this case, let's go to our create_posts_table and all we have to do is add another foreign ID for the team. So let's go make one.
foreign ID for the team. So let's go make one. So for an ID, let's call it teamId. So this will keep track of the team that created this Post. Okay. So we have to make a change on the PostController since we're now storing the teamId. And we want to change the store method, so let's look for that. And we just want to add the teamId here. So I'm going to do teamId. And to get the current user's team or current team.
So I'm going to do teamId. And to get the current user's team or current team. So the one they are signed in as, oh yeah. So what I said was correct earlier, but I want to make sure that I am within Andre's team. So right now I'm logged in as Will, but I'm logged in as my own personal team. So I'd have to switch to Andre's team. And this is still the same, but now I'm signed in as Andre's team. So this should still not show the buttons. Okay.
So this should still not show the buttons. Okay. So Jetstream has a bunch of handy methods available on the User model. If you scroll up here, right here. So all of these, they're pretty self-explanatory. So just read them and they should make sense. We'll make use of some of them here. So in this case, when we're creating a new Post, we want to keep track of the user's logged in team. So in this case, we just want the current team.
logged in team. So in this case, we just want the current team. So let's do that in our code. So auth, let's grab the user and say currentTeamId. Okay. So that's just a field like that. So now we're keeping track of the user that created the post and also the team they are signed in as. Let's also change our seeder here. So DatabaseSeeder, and let's add a teamId as well for the posts here.
Let's also change our seeder here. So databaseSeeder, and let's add a teamId as well for the posts here. Let's add a teamId and it's going to be $userA->currentTeamId and same for this. And this is $userC. Okay. And let's go ahead and re-migrate our database. So php artisan migrate:fresh --seed. Now I'm going to sign in as $will again. Nothing has changed so far. So let me just refresh this. And I'm not signed in because I re-migrated the database.
Updating Blade and Controller Checks9:18
So let me just refresh this. And I'm not signed in because I re-migrated the database. So let me just sign in as well again. Okay. And let's go back to Andre's post. Nothing has changed so far. So we do want to show this button because Will is a part of Andre's team. So let's go ahead and go to the show.blade.php here. And let's change the permission here for the edit button. And it's going to be the same for delete for now.
And let's change the permission here for the edit button. And it's going to be the same for delete for now. So it's pretty much the same thing. Let me just comment this one out. Let me just duplicate it first actually then comment this one out. And what we're checking now instead of the user's ID is the user's team ID. So we can do $user to grab the user. We want to grab the current team they're logged in as so currentTeam. And we want to grab their ID. And that's just a field.
We get a 401 Unauthorized. So we just basically have to take the same permission here. So let me just grab this and put it in the PostController. And we just have to replace the three ones that we have here. So one for edit. So let's remove this or replace this. And it has to be the negated case. So let me just add 401 here. And it should be not like this.
So let me just add 401 here. And it should be not like this. Okay. Let's grab this. Let's put it on here as well. And like I said earlier, this should be in a Policy to make it cleaner and not have this duplication. But for demo purposes, I'm just putting it in the Controller here. Okay. And this should work now.
Enforcing Roles and Permissions12:22
team and it doesn't cool. So let me just go back here to Andre's Post. And at this point, we're not checking any of the permissions or any of the roles. We're just checking if this person is on Andre's team. And for a lot of cases, that's fine. But let's see how we can respect the permissions or the roles. So let me go into the edit page here. And let's see how we can check the role. So back here, let's go into our PostController, start with edit. And I just noticed you can also do not equal here instead of putting the not in front,
So back here, let's go into our PostController, start with edit. And I just noticed you can also do != here instead of putting the not in front, which is the same thing. So I'll just leave it like this. Actually, no, it's cleaner like this, I think. So let me just change these here. Okay. And let's check roles here. So back to edit. And let me duplicate this comment is out.
So back to edit. And let me duplicate this comment is out. And now we need the not sign here. And we can make use of the hasTeamRole method. And let's take a look at what that does. Let's look for hasTeamRole. So it takes in the team. And we just check for the role as a second argument. So it's going to be off user currentTeam for the team. And let's check if they are an editor.
So it's going to be off user current team for the team. And let's check if they are an editor. So let's pass an editor here as a second argument. Okay. And let's close out this bracket. Okay. I think that's right. So this should still work because will is an editor. And it does. But if I were to change this to admin, will is not an admin.
And it does. But if I were to change this to admin, user is not an admin. So this should be a 401. And it is cool. And if you want to make use of permissions instead of roles, then it's almost the same. Let me just comment this one out. And instead of hasTeamRole, we can do hasTeamPermission. The first parameter is the team and the second parameter is the permission. So in this case, we want to check if we have the update permission. And we do.
So in this case, we want to check if we have the update permission. And we do. So this should still work. But if we put another permission in here that we don't have access to, or if I were to remove the update on the editor, let's do that instead. Let's StreamServiceProvider. Let's remove update from editor. So editors can no longer update. This should be a 401. And it is cool.
This should be a 401. And it is cool. Let me just put that back. And I'll just stick to this one here. And we also have to do this in the view as well. Let me just paste these in here. Okay. And here as well. Okay. And let's go back to the show.blade.php for now.
Okay. And let's go back to the show Blade for now. So back here. And it's added for here as well. So it's pretty much the same thing. Just the not negated version. So let me just grab one of them here. So this check right here. And it's based on in here. And this one's for updating.
