This episode is for members only

Sign up to access "Laravel Teams" right now.

Get started
Already a member? Sign in to continue
Playing
18. Removing a team member

Episodes

0%
Your progress
  • Total: 4h 36m
  • Played: 0m
  • Remaining: 4h 36m
Join or sign in to track your progress
01. Introduction and demo
4m 49s
0%
02. Setup with Pest
4m 2s
0%
03. Building the user teams relations
6m 5s
0%
04. Creating a personal team when registering
6m 3s
0%
05. Leaving all teams when an account is deleted
3m 55s
0%
06. Tracking the current team
4m 50s
0%
07. Showing team details in the UI
2m 55s
0%
08. Switching to another team
7m 24s
0%
09. Authorising team switching
6m 53s
0%
10. Updating a team name
10m 48s
0%
11. Basic roles and permissions setup
5m 26s
0%
12. Team roles and permissions middleware
9m 18s
0%
13. Authorising current team updates
3m 43s
0%
14. Testing team permissions through HTTP requests
3m 58s
0%
15. Leaving a team
10m 50s
0%
16. Displaying team members
8m 42s
0%
17. Making team members look better
5m 3s
0%
18. Removing a team member
15m 18s
0%
19. Preventing self removal from a team
4m 7s
0%
20. Storing invitations
13m 31s
0%
21. Validating invitations
6m 38s
0%
22. Authorising team invitation creation
6m 22s
0%
23. Displaying invitations
3m 16s
0%
24. Revoking invitations
12m 46s
0%
25. Sending an invitation email
13m 6s
0%
26. Accepting an invitation
12m 22s
0%
27. Displaying a modal to change a member’s role
10m 31s
0%
28. Updating a member’s role
9m 5s
0%
29. More authorisation and checks for role changing
10m 14s
0%
30. Fixing up the email sending test details
49s
0%
31. Fixing and validating email addresses for invites
1m 32s
0%
32. Tidying up @can directive checks
3m 25s
0%
33. Detaching roles when removing users
5m
0%
34. Adding an extra layer of protection to the team middleware
6m 35s
0%
35. Getting related models through teams
5m 37s
0%
36. Building a helper to access the current team
10m 47s
0%
37. Getting all related models through all teams
7m 15s
0%
38. Creating new teams
13m 7s
0%

Transcript

00:00
Removing a team member might seem pretty straightforward. We go ahead and just detach that user from that team. But there are a couple of other things that we need to take into account.
00:08
Let's go ahead and get this built. We'll obviously write some tests to back this up and then we'll go ahead and demo it in the UI just to make sure. Okay so first of all let's go ahead and create out a new controller specifically for team member things. We won't clutter our team controller which directly relates to our team.
00:27
Let's go ahead and make a team member controller instead and let's go ahead and create out a route for the removal of a member of a team. So we're going to make this a delete request that kind of makes sense and we're going to use the same URL pattern fetching the team that we are actually removing from and then members and then in here the user. So let's switch this over to the team
00:55
member controller. Make sure we pull that in and we'll just get rid of this here and we're just going to call this destroy. Call it whatever you want. So now we're going to say team members dot and let's call this destroy and there we go. Okay so now that we've got this controller let's create out that destroy method and let's just go ahead and die dump in here on anything and let's make
01:19
sure we pull in the team that we want to remove this user from and the user or the member that we want to remove. So I'm actually going to call this member. Okay now that we've got this let's go over to our team member item and let's change this over so it works with a form. Let's create our form out here. We know what the action is so let's go ahead and go through to that team members and
01:42
destroy. Now in here we need to pass in two items so to do that we do this directly within an array. Now we have access to the member but we don't have access to the team in here as a prop. Now there are a couple of ways that you could do this. You can find the member who is part of this team but really the easiest way to do this would be to go ahead and just pass this down. So we'll pass
02:06
this down as a prop as well. Let's pass that directly into here and then we should have access directly to that in here. Okay let's set the method here to post and let's go ahead and add in our cross-site request forgery token and because we're making a delete request we need to spoof this method to be a delete. Then we can just add a button here with a type of submit and we can just
02:31
add in any of the text that we need. So let's just say remove from team. Okay that should be just about it. Let's go over and just try this out and make sure it submits through. So let's say remove from team and there we go we're through. Now as part of this we also need to make sure that we can't remove ourselves from the team. That's really important so we'll go ahead and figure
02:52
that out in the next episode. Okay so how do we remove a member from a team? Well like I said the easiest way to do this is just to access the members relationship from that team and go ahead and just detach that user. That's the easiest way that we can do that. It's just going to get rid of them but we need to figure out or in this case member but we need to figure out what's going to
03:12
happen to that member. Well their current team id in the database is still going to be attached to this team so when they log in there's probably something's going to go wrong. So let's go ahead and fill this in now just to make sure that this works. So let's redirect and we'll go specifically over to the team edit route and let's just try this out first of all. So we can always re-add
03:35
this member manually. So let's click remove from team and we're redirected back and that didn't work. I have a feeling that we are because we're using root model binding we need this variable to be the same so let's just give this the name of user just to keep things simple. Okay let's try this out one more time so remove from team and there we go that user has been removed. However
03:55
over in the database if we head over to teams we've just removed that user from team seven. If we head over that's still set to seven so we're going to need to figure that out as well. So let's go ahead and do that now and then we'll write a test just to make sure this is working and we're good to go. So let's say user so the user that has just been detached we want to
04:16
re-associate the team that they are currently in. So again we already did this earlier when we left a team so it's going to be exactly the same thing. We want to take that user's teams grab the first one we will always know they're going to have one and associate that with the first team and then just save that out. So that will just update the user with their personal team or any of the other
04:36
teams that they're in. Okay now that we've done this let's go ahead and write some tests so because we've created our new controller let's go ahead and make out a new test and we'll call this team controller test or team member controller test and let's open that up and start writing some tests for this. Okay so the first one is just going to be the best case scenario so it can remove
04:57
a member from the team so let's get rid of what we've got here with the boilerplate and let's get started. So let's say user factory create this is going to be the user who's going to be doing the removing of that user. We need another member as part of this team so we just use the current team that's being generated so let's grab the members from the current team and attach
05:20
another member exactly like what we've just manually done in the database with that new member we've deleted. So let's go ahead and create out a new user and this is going to be the member that we're going to detach from the team. Okay so what we need to do because this member when they're created has a current team id set to their personal team we need to manually switch the member
05:43
that's being removed to the team that they're being removed from so let's say member current team and go ahead and set that so we'll associate that with the user's current team so basically switch them over to that team. Okay so now that we've done this we can go ahead and act as that user who's going to do the deleting send a delete request down and we know that root is now team
06:10
and members and destroy of course we need to pass down the team which is the user's current team and we need to pass down the member as well. Okay now that we've done that we want to assert that we get a redirect so that's basically so assuming that this has been successful and let's go ahead and run this test and just make sure this is working so let's go ahead and run the team member
06:33
controller test and see what we get. Okay we get failed just because we haven't pulled in the user model let's go ahead and do that now and let's rerun that. Okay yeah that passed so great we have been redirected but we want to do a couple of other checks here we want to check that that member has actually been removed so we've been redirected but that doesn't give us the confidence
06:53
that the user has actually been removed so let's expect the user who has done the deleting will fresh them up so we get that from the database and we want to check the inside of that current team the members does not contain that user so we're going to say contains member to be false so basically make sure that the member that we've just deleted does not exist
07:18
let's rerun that and yeah that looks good let's also make sure as part of this test that the user's current team id has been changed the one that's been removed so let's say and member again we're going to say fresh to get the fresh data out of the database and current team id and obviously we can directly check the current team id or we can check the relation itself and we want to make
07:41
sure that this is not equal to the user's current team id so basically make sure that that's been switched to anything else aside from this user's team id who's done the deleting okay let's go ahead and run our test and we get green so we know that that is working nicely we've already kind of seen that in the ui but at least we know that this is working now okay so another really important part
08:05
about this is whether we have permission to remove users from the team so we haven't actually updated our admin role cd yet so let's go ahead and add in the ability to remove team members in here and we'll go ahead and run our cd for this to get that in the database great and let's go ahead and write a test for this now which of course is going to fail but then we can go ahead and add in the
08:32
policy that we need so we're going to say cannot remove a member from the team without permission and let's go ahead and fill this in so it's pretty much going to be the same thing that we've already done just to sort of amalgamation of everything so let's go ahead and create out the user who's going to be doing the deleting we're going to set out another user in here
08:58
with user factory again and we're going to do exactly the same thing that we did here as well and we're going to attach another member so basically acting as this user we're going to try and delete this user from this user's team which they're obviously not going to be able to do so let's go ahead and act as another user trying to delete that member from the user's
09:26
team so send a delete request down to this route and that's team members destroy again let's pass in the team that we're trying to delete from which is the user's current team and the member is the thing that we're trying to delete from that other person's team so basically we shouldn't have permission to do this and of course again we're going to use that assert forbidden method okay
09:50
let's go ahead and run our tests here and see what happens and it does fail which is great we get a 302 redirect and we are expecting a forbidden so at the moment in the state of our application we can remove other team members from other teams which obviously isn't great so again we're going to head over to our team policy now you could create out another policy for this
10:14
if you wanted to but i'm going to keep everything in one single team policy because although we've created a different controller everything does still relate to one team so what is this going to look like well let's call this remove team member kind of makes sense we're going to get the user into here we're going to get the team into here but this one is slightly
10:34
different because now we're dealing with this specifically for a member so we're introducing another argument into this method so we know that at the bottom of here we're always going to use the user can remove team members and this is what we're testing for at the moment but there's something else that we need to test as well we need to make sure the user is actually in that
11:01
team before we go ahead and remove them now this doesn't really matter too much so this is the most important thing remember this is always going to be done in the context of the current team we're in via that middleware that we've set making sure the user is actually in the team isn't too much trouble because of the way we've set up our controller let me show you what i mean so what
11:23
we're doing here is the team that we pass in we're trying to remove this user but what we're doing is we're accessing the members only of that team so even if we were to pass a completely random user in here that didn't belong to the team it wouldn't detach them because they wouldn't be within the members list in the first place so this kind of thing is good in it kind of mimics what we were
11:47
doing in the policy because we're basically only saying remove this user from that list of team members we're not manually modifying the database we're doing this via a relation which makes it a safer option so we will add a check in our policy to do that but it's never really going to get to that point so it doesn't really matter okay so now that we've done that let's go back
12:08
over to our team member controller and in here let's bring in a request to deal with this so let's go ahead and create our a request here and let's call this team member destroy request that makes sense and let's switch this out here so team member destroy request and there we go so now really all we need to do in here is just change over the authorization so if this user can remove
12:39
team member and remember we need to pass in multiple options here so that is going to be from this team and it will be this user okay now we've got this policy in here let's go ahead and run this test again and yeah we get two failed this time so let's just have a look here so yeah we should just need to pull in team and member oh okay so we've called this member
13:03
obviously that's a user that kind of makes sense okay let's run that test okay so we still get a fail here and yeah it's for exactly the same reason now let's think about this so remember that these checks are within the context of the current team that we're working on now this isn't anything wrong with our code if we were to do this in the ui it would work but it's to do with our
13:25
test now remember that when we act as a user they will always be in the context of their current team via that middleware so what we're going to have to do again within this test is just say without middleware and we have that team permission middleware in here so we'll exclude that and then we'll go ahead and set the permissions team id in here to the team that they are within so
13:49
basically we have this other user who whether they're a part of that team or not don't have permission based on the team that they're currently attached to so let's go ahead and set the id to the user's current team id so they're now within that team that means that the checks that we have in our policy here will always be done in the context of this team and this doesn't really
14:11
matter because we're just using this in the url to remove them from that specific team okay let's try this one more time and yeah there we go it passes so just remember that when we're doing these checks they're always in the context of that middleware which if we're running our tests will always kick in if we are sending http requests so we remove that manually set this and we're good
14:32
to go so we can add one more check to this so we could say if the team members doesn't contain that member then we can return false so that's just an additional thing if the user doesn't exist within that team or this member doesn't exist within that team our test should still pass here but we could write a specific test for that but like i said over in the team member controller
14:57
we're only removing this member from the team members list so even if a user that didn't belong to that team was passed in it wouldn't work this is just here just in case okay there we go so we might come back and tidy this up later but there is our bunch of tests let's just run all of them just to make sure and yeah we're all good so we can now remove users from teams
38 episodes4 hrs 36 mins

Overview

Need team functionality in your Laravel application? Let’s build it from scratch.

We’ll cover the basics of creating teams, switching between them, sending secure team invites by email, and managing team members.

Powering everything will be roles and permissions for each member, with the ability to switch roles directly from your team dashboard.

Once you’re done, you’ll have mastered team functionality in Laravel.

Alex Garrett-Smith
Alex Garrett-Smith
Hey, I'm the founder of Codecourse!

Episode discussion

No comments, yet. Be the first!