We continue with the roles and permissions section in Laravel. This part is going to be a bit dense, since we are going to do a lot of things. We will create a mini administration of users and we will be able to change their role and also we will be able to activate and deactivate users. All this, we can do it if our user has the administrator role.
First, we are going to start creating the controller. As usual, we will use the command that Laravel provide us.
1 |
php artisan make:controller Admin\UsersController |
And add this code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
<?php namespace App\Http\Controllers\Admin; use Illuminate\Http\Request; use App\Http\Controllers\Controller; use Illuminate\Support\Facades\Auth; use App\User; use Spatie\Permission\Models\Role; class UsersController extends Controller { public function index() { $users = User::all(); $roles = Role::pluck('name', 'name'); return view('admin.users.index', ['users' => $users, 'roles' => $roles]); } public function activeDeactive(Request $request) { if (Auth::id() != $request->user_id) { $user = User::findOrFail($request->user_id); $user->active = !$user->active; $user->save(); return redirect()->route("admin.users.index")->with('success', $user->name." status has been changed!"); } else { return redirect()->back()->withErrors(['You can\'t change your status!']); } } public function changeRole(Request $request) { if (Auth::id() != $request->user_id) { $user = User::findOrFail($request->user_id); $user->syncRoles($request->role); return redirect()->route("admin.users.index")->with('success', $user->name." role has been changed!"); } else { return redirect()->back()->withErrors(['You can\'t change your role!']); } } } |
It has 3 methods:
- index: it sends the list of users to the view. And also the roles to show in the popup to change the role.
- activeDeactive: it activates and deactivates the indicated user.
- changeRole: it changes the role of the indicated user.
Create the view for the list of users and the popup for the change of role (index method):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
@extends('layouts.app') @section('content') <div class="container"> <div class="row"> <div class="col-md-8 col-md-offset-2"> <h3>User list</h3> @include('includes.errors') @if(session()->has('success')) <div class="alert alert-success"> {{ session()->get('success') }} </div> @endif <table class="table table-bordered table-striped"> <thead> <tr> <th>#</th> <th>Name</th> <th>Email</th> <th>Role</th> <th>Options</th> </tr> </thead> <tbody> @forelse ($users as $user) <tr class="{{ ($user->active == 0) ? 'danger' : '' }}"> <td>{{ $user->id }}</td> <td>{{ $user->name }}</td> <td>{{ $user->email }}</td> <td> @foreach ($user->roles()->pluck('name') as $role) <span class="label label-default">{{ $role }}</span> @endforeach </td> <td> @if (Auth::id() != $user->id) <button type="button" class="btn-modal-change-role btn btn-info btn-sm" data-userid="{{ $user->id }}" data-userrole="{{ $role }}">Change role</button> {{ Form::open(['route' => ['admin.users.active_deactive'], 'method' => 'POST']) }} {{ Form::hidden('user_id', $user->id) }} {{ Form::submit(($user->active == 0) ? 'Reactive' : 'Deactivate', ['name' => 'submit', 'class' => 'btn btn-warning btn-sm']) }} {{ Form::close() }} @endif </td> </tr> @empty <tr> <td colspan="5">No results</td> </tr> @endforelse </tbody> </table> </div> </div> </div> <div class="modal fade" id="roleModal" role="dialog"> <div class="modal-dialog modal-sm"> <div class="modal-content"> <div class="modal-header"> <h3>Change role</h3> </div> <div class="modal-body"> {{ Form::open(['route' => ['admin.users.change_role'], 'method' => 'POST']) }} {{ Form::hidden('user_id') }} <p>{{ Form::select('role', $roles, null, ['class' => 'form-control']) }}</p> {{ Form::submit('Change', ['name' => 'submit', 'class' => 'btn btn-success btn-block btn-change-role']) }} {{ Form::close() }} </div> </div> </div> </div> @endsection |
Now, we are going to add the routes, but first we are going to create a middleware to check if the user has the administrator role:
1 |
php artisan make:middleware RoleMiddleware |
And add this code, we can see it on the package documentation:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?php namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\Auth; class RoleMiddleware { /** * Handle an incoming request. * * @param \Illuminate\Http\Request $request * @param \Closure $next * @return mixed */ public function handle($request, Closure $next, $role = null, $permission = null ) { if (Auth::guest()) { return Redirect::guest('login'); } if (!$request->user()->hasRole($role)) { abort(403); } if ($permission != null && !$request->user()->can($permission)) { abort(403); } return $next($request); } } |
Register it:
1 2 3 4 |
protected $routeMiddleware = [ ... 'role' => \App\Http\Middleware\RoleMiddleware::class, ]; |
Once we get this done, we can add the routes with the middleware:
1 2 3 4 5 |
Route::group(['middleware' => ['auth', 'role:administrator'], 'prefix' => 'admin', 'as' => 'admin.'], function () { Route::get('/users', 'Admin\UsersController@index')->name('users.index'); Route::post('/users/active_deactive', 'Admin\UsersController@activeDeactive')->name('users.active_deactive'); Route::post('/users/change_role', 'Admin\UsersController@changeRole')->name('users.change_role'); }); |
Now, we are going to add in the header the administration link:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
@role('administrator') <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false"> Administration <span class="caret"></span> </a> <ul class="dropdown-menu" role="menu"> <li> <a href="{{ route('admin.users.index') }}"> Users </a> </li> </ul> </li> @endrole |
It is showed just if the user has the administrator role, this is done with the @role tag.
Open app.js and add this code to show the popup to change roles:
1 2 3 4 5 6 7 8 9 10 11 |
$(document).ready(function(){ $(".btn-modal-change-role").click(function(e) { var currentUserRole = $(this).data("userrole"); var currentUserId = $(this).data("userid"); // add the user id of the selected user to the input $("input[name='user_id']").val(currentUserId); // select current role for the user selected $("select[name='role']").val(currentUserRole); $("#roleModal").modal("show"); }); }); |
And execute this command, in order that the js of the public folder is updated:
1 2 3 4 5 |
//if we are in development environment npm run dev //if we are in production environment npm run prod |
The result would be this: