00:02
So now the last feature that we have to tackle for our organization settings page is the ability to remove an organization member.
00:11
So let's go ahead and jump back into our terminal here and start yet again by making our actions. So node ace make action, put this inside of our organizations folder
00:20
and call it remove organization user. Okay, we can clear that out, jump back into our text editor and let's go ahead and dive into that action. So remove organization user and we're gonna want two different things here.
00:30
The organization of type organization as always. And we're also gonna want the user ID that we actually want to remove out of this organization. And so that we take all possibility of confusion out of the equation,
00:40
let's go ahead and call that remove user ID and give it a type of number. Within our handle method, we can go ahead and grab the organization as well as that remove user ID.
00:50
And how difficult you wanna get with this actual operation is completely up to you. If you just want to await organization related users
00:58
and detach the desired removed user from this organization and call it a day, what would be a little bit more of a catch all situation for this though, is if we treated this a little bit more
01:07
like our account deletion action. So for example, if we jump back into our destroy user account action, we have this delete dangling organizations, where it takes in the user and it checks for organizations
01:17
where that user is the only member and then deletes them out if any are found. So in the case of our remove organization user, we could use the same premise just a little bit differently.
01:27
We could check to see whether or not this specific organization only has this specific user inside of it. And if it does, then we can go ahead and delete that organization as well. And that would also allow for any user
01:37
to be able to safely remove themselves out of the organization. Then if it's just the last person removing themselves, we just delete it out of the database. So before we actually detach the user,
01:46
let's go ahead and get an other user out from our organization. So we'll use our organization, reach for the related users.
01:55
And then we can query with this. I'm gonna give myself a couple of line breaks to work with here. And then we wanna do where not the ID is the remove user ID.
02:05
And then we can go ahead and count them up by their IDs. Give that a save to format it and then we'll walk through what we have here. So for the specific organization that we're wanting to remove this user from,
02:14
we're reaching through that organization to its users and counting them up by their IDs. Then we're removing from that count the specific user that we're looking to remove.
02:23
So we know that if our other user count is zero, then the removed user is the only user inside of the organization. And we can go ahead and delete it out.
02:31
Now, of course, remember we are dealing with models here. So the other user count is not going to actually be our count, but rather our user model array.
02:39
So let's also tack on here a first or fail. Since we're doing a count, it will just come back with a user model with our extras populated. And then we can go ahead and wrap this in a transaction.
02:49
So await DB transaction async, get our transaction here set up, move our detach into that transaction.
02:57
And then where we actually delete the organization doesn't really matter because the detachment here from the user would go ahead and cascade with the organization's deletion.
03:06
But we'll go ahead and do it after the detach. If other user count dot, and we want to reach through the extras. And I want to say that's going to come through as count,
03:16
but I'm not 100% sure I am remembering that correctly. So I'll tell you what, let's jump into a REPL session real quick. Node Ace REPL, let's await load models.
03:26
And let's go ahead and grab our organization as await models organization. And let's find by or fail the organization name
03:36
where it is my second organization. So my second organization, run that. And we should have now our organization populated.
03:46
And now we can go ahead and do awaits, which through our organizations related users, query from there. And all I really care about is what this property is called.
03:55
So I'm just going to go ahead and run a count and let's plop this into user counts. All right, hit enter there to run it. And okay, the ID is ambiguous between our organization and users.
04:05
So let's hack on our users ID within our count, run that. And now user counts already defined.
04:12
All right, let's just switch that name there to count. Run that, there we go. Now we have our count. We can reach to the first index, which is where our actual count will be.
04:22
And then reach through to the extras object. Yeah, okay, so we have count of four. And you'll notice that it's a string. So that's what we're going to be working with right here
04:31
where we have our extras count. So we can either turn that into a number and do a greater than check, or we can just see whether or not it equals zero. If it equals zero, then we know that we're okay to go ahead
04:41
and delete the organization because that means that this removed user is the one and only user from that organization. So at that point we can await organization and just call the delete method.
04:50
Before we call this done and dusted though, we actually need to rig our transaction up to these operations. And since the detachment goes through our organization, and then we just delete the organization itself,
05:00
the only thing that we need to bind the transaction to is our organization. So we'll say to use the transaction here off of our organization, just like so.
05:08
And now we can call this action done and dusted. Let's jump back into our organization controller within our settings, because we now need to fill out our remove user method.
05:17
So for this, we'll have our response, the organization, programs, and session from our HTTP context.
05:24
We can go ahead and await remove organization user, call the handle method, pass that organization on in. And then we also have our remove user ID,
05:34
which will come from our programs ID. Once we have removed the user, we can go ahead and session/success, member has been successfully removed,
05:43
and then return response redirect on back. Now you might be wondering what about the use case where the organization is actually deleted within this action?
05:53
Do we indeed actually just want to redirect them back like nothing happened? And the answer is, yeah, we can. We set up our organization middleware so that we'll successfully check and see whether or not the organization's there,
06:03
and then load in another organization that the user is bound to if it is not. And then in addition to that, it will also redirect them back to the create organization page
06:12
if the user is not bound to any organization at all. So in the case where the user is removing themself from the organization and they are the one and only user inside of the organization,
06:21
our system via our organization middleware is rigged up okay to handle that successfully. So let's jump now back into our organization users card,
06:30
where we have just like in the last lesson, our empty table cell here to fill out a inertia link with our action to remove the user. Go ahead and end that link out,
06:39
and break this down into new lines, and we can rig up the actual href and point that to /settings/organization user,
06:47
and then plop the member ID of the member that we are currently looping over right up here in our table row. Okay, then this is a destructive action.
06:57
So we'll set the method to delete. We also need to set the route up. I almost forgot about that. So we'll do that here momentarily. Last text read 500, and then of course,
07:06
reserve that scroll position just in case the user is not deleting themselves, which is most likely going to be the case. All right, now just like in the last lesson, I also forgot the as prop here as well. So we'll add in our as button
07:16
so that this is rendered out as a button element rather than an anchor element. All right, we can give that a save, and then let's jump back into our web routes so that we can rig this route up.
07:25
So router, we'll have another delete here pointing to our settings, organization, user, and then tack the user ID on there.
07:34
I have this go to settings, organizations, controller, and bind it to our remove user method. As, settings, organization, user, remove.
07:44
There we go. Okay, with all that set, let's jump back over into our browser now. And there we go. We can immediately see our remove buttons across everybody. And let's go ahead and try to remove test invite three.
07:54
So let's click remove right there. And ran into that issue within our REPL, but I completely forgot to account for it inside of our actions. Let's jump back down
08:02
into a remove organization user action. See, where is this? Right here, where we have our count. Again, the ID column that we're counting by is ambiguous between our organization
08:12
and the users that is joining in. So we need to specify that this is from our users table there. But in this case, we also have the users being referenced on our where not there as well.
08:21
So we also want to update it there too. So let's tack our users.id on there so that both of those know which table we're referencing the ID column off of within that join.
08:31
Okay, give that a save. Now we can jump back into our browser. Let's go and get rid of that pop-up. I'm gonna give this a sanity refresh here. We can jump back down, click remove. There we go.
08:41
Member has been successfully removed and we see them out of our organization members now. Let's go ahead and jump over to one of these other organizations that we have set up. We'll do my fourth,
08:51
we'll jump down to the last one here in the list and jump over into the organization settings within here, where we are confirmed to be the only user inside of this organization.
08:59
Let's go ahead and try to remove ourselves. And there we go. Member has been successfully removed. And in addition to that, we are now switched back over to my second organization
09:09
and my fourth organization is removed out of our organizations list. And it should have been removed out of our database altogether.
09:17
So if we go ahead and I'm gonna exit out of here, clear that out, node ace, REPL await load models and await models organization,
09:26
find by the name my fourth organization, we get back null as our result. So it indeed did not find it in the database there either.