Teams Multi-Tenancy: Add “Team Admin” to Manage Users

Founder of QuickAdminPanel
By default, in our Team Multi-Tenancy module, every member of the team sees all entries of their team, and team users are managed only by the system administrator. Customers were asking us how to add a new role of “Team Admin” to manage users of their own team. So we created a demo-project with a repository.
As a starting position, I assume that you have already generated the adminpanel with Multi-Tenancy module and chose “Team” multi-tenancy, not “User”.
Next, I will show you the actions in 6 steps, how to add “team admin”.
Step 1. Add new field in User model
We won’t add a new role to the existing ones (Admin & User), we will just add a field: users.team_admin – you can add it in QuickAdminPanel as a checkbox, or after download as “boolean” field in migrations and app/User.php.
Default should be false.
Schema::table('users', function (Blueprint $table) { $table->boolean('team_admin')->default(0)->nullable(); });
Step 2. User Model: Is Team Admin – Attribute
Let’s add another attribute to app/User.php that would check if user is system admin or team admin:
// That method exists by default in QuickAdminPanel public function getIsAdminAttribute() { return $this->roles()->where('id', 1)->exists(); } // That is new method public function getIsTeamAdminAttribute() { return $this->is_admin || $this->team_admin; }
After doing that, we will be able to check it from anywhere, like $user->is_team_admin or auth()->user()->is_team_admin. And we will do exactly that, in the next step.
Step 3. Menu: show Users for Team Admin
By default, only System Administrator sees Users Management menu item in the left sidebar. Let’s change it.
We will use the new is_team_admin attribute, see below.
@can('user_management_access') @if(auth()->user()->is_team_admin) <li class="nav-item nav-dropdown"> <a class="nav-link nav-dropdown-toggle" href="#"> <i class="fa-fw fas fa-users nav-icon"> </i> {{ trans('cruds.userManagement.title') }} </a> {{-- ... other sub-menu items --}} </li> @endif @endcan
Also, we need to allow user_management_access to all users then. So we need to edit database/seeds/PermissionRoleTableSeeder.php:
Old:
$user_permissions = $admin_permissions->filter(function ($permission) { return substr($permission->title, 0, 5) != 'user_' && substr($permission->title, 0, 5) != 'role_' && substr($permission->title, 0, 11) != 'permission_'; });
Now:
// Simple can't manage roles/permissions/teams, but can manage users now $user_permissions = $admin_permissions->filter(function ($permission) { return substr($permission->title, 0, 5) != 'role_' && substr($permission->title, 0, 11) != 'permission_' && substr($permission->title, 0, 5) != 'team_'; });
Step 4. Additional Security in Controller
Of course, it’s not enough to show/hide menu items. We need to make sure that non-team-admins wouldn’t access user management.
app/Http/Controllers/Admin/UsersController.php:
public function index() { // Old version: // abort_if(Gate::denies('user_access'), Response::HTTP_FORBIDDEN, '403 Forbidden'); // New version: abort_if(Gate::denies('user_access') || !auth()->user()->is_team_admin, Response::HTTP_FORBIDDEN, '403 Forbidden');
And you need to repeat that change in all of UsersController methods.
Step 5. User model is Multi-Tenant now
By default, users don’t have multi-tenancy but now they should. So we make these changes in app/User.php – see in bold:
use App\Traits\MultiTenantModelTrait; class User extends Authenticatable { use SoftDeletes, Notifiable, HasApiTokens, MultiTenantModelTrait; // ... other model's code
Step 6. User Create/Edit Form: Change Visible Fields
Finally, we need to change which role sees what fields in user form.
– Administrator can choose a role, team admin can’t (role is hardcoded as Simple User then);
– Administrator can choose a team, team admin operates only within their own team.
For that, we make changes in resources/views/admin/create.blade.php and same folder edit.blade.php. These are too big files to add here inline, so here’s a link to the repository commit.
See here – team administrator doesn’t see the role and the team choices.
And that’s it. By then, your Team Admin users will be able to add/edit other users of the same team.
Full code with repository changes: LaravelDaily/QuickAdminPanel-Team-Admin-Demo
Try our QuickAdminPanel generator!
7 Comments
Leave a Reply Cancel reply
Recent Posts
Try our QuickAdminPanel Generator!
How it works:
1. Generate panel online
No coding required, you just choose menu items.
2. Download code & install locally
Install with simple "composer install" and "php artisan migrate".
3. Customize anything!
We give all the code, so you can change anything after download.
So this will also fix the problem whereby a multi-tenant user can see the Admin when they have access to the User Management menu? Teams is really just an extension of user management.
Thanks for the information, worked well!
I have changed my MultiTenantModelTrait so that the Admin is also connected to one team, but actually that is not working for the User Model, as the Admin should see all users. has anyone an idea how I can change the MultiTenantModelTrait so that the GlobalScope is not running for the User Model?! Thanks
There’s a method in Eloquent, called withoutGlobalScope
User::withoutGlobalScope(AgeScope::class)->get();
Hi,
we have solved this that way:
static::addGlobalScope(‘team_id’, function (Builder $builder) use ($isAdmin) {
if(!$isAdmin or !is_a($builder->getModel(), ‘App\User’)) {
$field = sprintf(‘%s.%s’, $builder->getQuery()->from, ‘team_id’);
$builder->where($field, auth()->user()->team_id)->orWhereNull($field);
}
});
I would like to understand why you chose to add a field to users table and not instead create a team admin role, and allow users with that role to do user management restricted to the team that the team admin belongs to?
I would think that it would be a cleaner solution, not requiring an add to the users table, and in line with the roles approach 🙂
I agree, that’s another approach you’re suggesting. For me personally, my way seemed more simple, but yours is more flexible, I guess.
Can somebody please explain the “more flexible” way what Ken has mentioned? Thank you. May be it can open more avenues for the QuickAdminPanel users?