Laravel 5.4 User Role and Permissions with Spatie Laravel Permission

Laravel 5.4 User Role and Permissions with Spatie Laravel Permission

In this Laravel tutorial, I will tell you how to implement role and permission (ACL) to a user in the Laravel application.

For example, A user may have permission to change anything but other user may have permission to read only within the application.

In this example, I will create a simple blog application with role and permission that means you can give access to user to edit post, create post, delete post etc.

I will define role and permission on database level that will manage by a UI in the admin panel.

There are so many package built in Laravel to implement role and permission but for this example I am going to use spatie/laravel-permission package.

By the end of this tutorial, you will be able to define rights for authenticated users using role and permissions.

Install Laravel 5.5 and Configure the permission package

First, We will install fresh Laravel application by running following composer command :

composer create-project --prefer-dist laravel/laravel blog

After successfully installation, create the database and update database credential in .env file.

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=blog
DB_USERNAME=root
DB_PASSWORD=

Now install the Laravel permission package :

composer require spatie/laravel-permission

Now add the provider in the list of service provider, Open config/app.php file and add Spatie\Permission\PermissionServiceProvider::class.

'providers' => [
    ...
    Spatie\Permission\PermissionServiceProvider::class,
];

Now run the artisan command to publish migration file :

php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" --tag="migrations"

To create table from migration file, run following artisan command :

php artisan migrate

If you are running lower version of MySQL then you may get following error :

[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table users add unique users_email_unique(email))

[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes

To avoid this error, edit the app\Providers\AppServiceProvider.php file :

use Illuminate\Support\Facades\Schema;

public function boot()
{
    Schema::defaultStringLength(191);
}

Now you can run migrate command again to create table into database.

Laravel Collective HTML Form builder

Now install the Laravel Collective HTML Form builder to avoid the error "Class Form not found".

And then add provider to providers array

'providers' => [
    ...
    Collective\Html\HtmlServiceProvider::class,
];

Next add the aliases to aliases array :

'aliases' => [
      ...
     'Form' => Collective\Html\FormFacade::class,
     'Html' => Collective\Html\HtmlFacade::class,
], 

With the fresh installation of Laravel, You will have User model by default.

Now I need to create Role, Permission and Post models with their resource controller.

Spatie\Permission already have role and permissions model, you just need to publish them but I will create manually Model and Controller class by running following command :

// Create Role model and resource controller
php artisan make:model Role -c --resource

// Create Permission model and resource controller
php artisan make:model Permission -c --resource

// Create Post model with migration and resource controller
php artisan make:model Post -m -c --resource

By default Role and Permission class will extend default Model class :

  1. class Role extends Model { }

You need to edit Role and Permission class to extend \Spatie\Permission\Models\.

  1. // Permission Model
  2. class Permission extends \Spatie\Permission\Models\Permission { }
  3. // Role Model
  4. class Role extends \Spatie\Permission\Models\Role { }

When you run php artisan make:model Post -m -c --resource command then you will have migration file to create post table, So edit you migration file :

2017_09_02_052113_create_posts_table.php
  1. Schema::create('posts', function (Blueprint $table) {
  2. $table->increments('id');
  3. $table->string('title');
  4. $table->text('body');
  5. $table->timestamps();
  6. });

Run migrate command to create post table again.

Next we need to add HasRoles trait to User model.

  1. use Spatie\Permission\Traits\HasRoles;
  2. class User extends Authenticatable {
  3. use HasRoles;
  4. ...
  5. }
Default Permission

Next we will add some default permission in Permission Model :

  1. <?php
  2. namespace App;
  3. use Illuminate\Database\Eloquent\Model;
  4. class Permission extends \Spatie\Permission\Models\Permission
  5. {
  6. public static function defaultPermissions()
  7.     {
  8.      return [    
  9.      'viewPost',
  10.      'addPost',
  11.      'editPost',
  12.      'deletePost',
  13.      ];
  14.     }
  15. }

Now we will use Database seeder to seed data for testing our app.

database/seeds/DatabaseSeeder.php
  1. <?php
  2. use Illuminate\Database\Seeder;
  3. use App\Permission;
  4. use App\Role;
  5. use App\User;
  6. use App\Post;
  7. class DatabaseSeeder extends Seeder
  8. {
  9. /**
  10. * Run the database seeds.
  11. *
  12. * @return void
  13. */
  14. public function run()
  15. {
  16. // Ask for confirmation to refresh migration
  17. if ($this->command->confirm('Do you wish to refresh migration before seeding, Make sure it will clear all old data ?')) {
  18. $this->command->call('migrate:refresh');
  19. $this->command->warn("Data deleted, starting from fresh database.");
  20. }
  21. // Seed the default permissions
  22. $permissions = Permission::defaultPermissions();
  23. foreach ($permissions as $permission) {
  24. Permission::firstOrCreate(['name' => $permission]);
  25. }
  26. $this->command->info('Default Permissions added.');
  27. // Ask to confirm to assign admin or user role
  28. if ($this->command->confirm('Create Roles for user, default is admin and user? [y|N]', true)) {
  29. // Ask for roles from input
  30. $roles = $this->command->ask('Enter roles in comma separate format.', 'Admin,User');
  31. // Explode roles
  32. $rolesArray = explode(',', $roles);
  33. // add roles
  34. foreach($rolesArray as $role) {
  35. $role = Role::firstOrCreate(['name' => trim($role)]);
  36. if( $role->name == 'Admin' ) {
  37. // assign all permissions to admin role
  38. $role->permissions()->sync(Permission::all());
  39. $this->command->info('Admin will have full rights');
  40. } else {
  41. // for others, give access to view only
  42. $role->permissions()->sync(Permission::where('name', 'LIKE', 'view_%')->get());
  43. }
  44. // create one user for each role
  45. $this->createUser($role);
  46. }
  47. $this->command->info('Roles ' . $roles . ' added successfully');
  48. } else {
  49. Role::firstOrCreate(['name' => 'User']);
  50. $this->command->info('By default, User role added.');
  51. }
  52. }
  53. /**
  54. * Create a user with given role
  55. *
  56. * @param $role
  57. */
  58. private function createUser($role)
  59. {
  60. $user = factory(User::class)->create();
  61. $user->assignRole($role->name);
  62. if( $role->name == 'Admin' ) {
  63. $this->command->info('Admin login details:');
  64. $this->command->warn('Username : '.$user->email);
  65. $this->command->warn('Password : "secret"');
  66. }
  67. }
  68. }

Next run the seeder using following command :

php artisan db:seed

Ok, Everything is setup now.

Next we will perform simple CRUD operation on "Role", "Permission", "User" and "Post" module.

Register routes

Now add following routes in your routes/web.php :

Route::group( ['middleware' => ['auth']], function() {
    Route::resource('users', 'UserController');
    Route::resource('roles', 'RoleController');
    Route::resource('posts', 'PostController');
	Route::resource('permissions','PermissionController');
});
Master Layout 'resources/views/layouts/app.blade.php'

  1. <!DOCTYPE html>
  2. <html lang="{{ app()->getLocale() }}">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1">
  7. <!-- CSRF Token -->
  8. <meta name="csrf-token" content="{{ csrf_token() }}">
  9. <title>{{ config('app.name', 'Laravel') }}</title>
  10. <!-- Styles -->
  11. <link href="{{ asset('css/app.css') }}" rel="stylesheet">
  12. </head>
  13. <body>
  14. <div id="app">
  15. <nav class="navbar navbar-default navbar-static-top">
  16. <div class="container">
  17. <div class="navbar-header">
  18. <!-- Collapsed Hamburger -->
  19. <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#app-navbar-collapse">
  20. <span class="sr-only">Toggle Navigation</span>
  21. <span class="icon-bar"></span>
  22. <span class="icon-bar"></span>
  23. <span class="icon-bar"></span>
  24. </button>
  25. <!-- Branding Image -->
  26. <a class="navbar-brand" href="{{ url('/') }}">
  27. {{ config('app.name', 'Laravel') }}
  28. </a>
  29. </div>
  30. <div class="collapse navbar-collapse" id="app-navbar-collapse">
  31. <!-- Left Side Of Navbar -->
  32. <ul class="nav navbar-nav">
  33. &nbsp;
  34. </ul>
  35. <!-- Right Side Of Navbar -->
  36. <ul class="nav navbar-nav navbar-right">
  37. <!-- Authentication Links -->
  38. @if (Auth::guest())
  39. <li><a href="{{ route('login') }}">Login</a></li>
  40. <li><a href="{{ route('register') }}">Register</a></li>
  41. @else
  42. <li class="dropdown">
  43. <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
  44. {{ Auth::user()->name }} <span class="caret"></span>
  45. </a>
  46. <ul class="dropdown-menu" role="menu">
  47. <li>
  48. <a href="{{ route('logout') }}"
  49. onclick="event.preventDefault();
  50. document.getElementById('logout-form').submit();">
  51. Logout
  52. </a>
  53. <form id="logout-form" action="{{ route('logout') }}" method="POST" style="display: none;">
  54. {{ csrf_field() }}
  55. </form>
  56. </li>
  57. </ul>
  58. </li>
  59. @endif
  60. </ul>
  61. </div>
  62. </div>
  63. </nav>
  64. @if ($message = Session::get('success'))
  65. <div class="alert alert-success">
  66. <p>{{ $message }}</p>
  67. </div>
  68. @endif
  69. @yield('content')
  70. </div>
  71. <!-- Scripts -->
  72. <script src="{{ asset('js/app.js') }}"></script>
  73. </body>
  74. </html>
User Management Module

Now add following code in UserController.php :


  1. <?php
  2. namespace App\Http\Controllers;
  3. use Illuminate\Http\Request;
  4. use App\User;
  5. use App\Role;
  6. use App\Permission;
  7. class UserController extends Controller
  8. {
  9. /**
  10. * Create a new controller instance.
  11. *
  12. * @return void
  13. */
  14. public function __construct()
  15. {
  16. $this->middleware('auth');
  17. }
  18. /**
  19. * Show the application dashboard.
  20. *
  21. * @return \Illuminate\Http\Response
  22. */
  23. public function index()
  24. {
  25. $users = User::latest()->paginate();
  26. return view('users.index', compact('users'));
  27. }
  28. public function create()
  29. {
  30. $roles = Role::get();
  31. return view('users.create', compact('roles'));
  32. }
  33. public function store(Request $request)
  34. {
  35. $this->validate($request, [
  36. 'name' => 'required',
  37. 'email' => 'required|email|unique:users',
  38. 'password' => 'required|min:6|confirmed',
  39. 'roles' => 'required'
  40. ]);
  41. $user = User::create($request->except('roles'));
  42. if($request->roles <> ''){
  43. $user->roles()->attach($request->roles);
  44. }
  45. return redirect()->route('users.index')->with('success','User has been created');
  46. }
  47. public function edit($id) {
  48. $user = User::findOrFail($id);
  49. $roles = Role::get();
  50. return view('users.edit', compact('user', 'roles'));
  51. }
  52. public function update(Request $request, $id) {
  53. $user = User::findOrFail($id);
  54. $this->validate($request, [
  55. 'name'=>'required|max:120',
  56. 'email'=>'required|email|unique:users,email,'.$id,
  57. 'password'=>'required|min:6|confirmed'
  58. ]);
  59. $input = $request->except('roles');
  60. $user->fill($input)->save();
  61. if ($request->roles <> '') {
  62. $user->roles()->sync($request->roles);
  63. }
  64. else {
  65. $user->roles()->detach();
  66. }
  67. return redirect()->route('users.index')->with('success',
  68. 'User successfully updated.');
  69. }
  70. public function destroy($id) {
  71. $user = User::findOrFail($id);
  72. $user->delete();
  73. return redirect()->route('users.index')->with('success',
  74. 'User successfully deleted.');
  75. }
  76. }

In store() method, A new user is registered with selected roles.

In update() method, I will update the user details and update roles with sync method.

Use mutator in app\User.php file that will encrypt password while registering new user.

app\User.php

  1. public function setPasswordAttribute($password)
  2. {
  3. $this->attributes['password'] = bcrypt($password);
  4. }
User Views

There are three views required :

index.blade.php

This file will contain a HTML Table with list of all users.

  1. {{-- \resources\views\users\index.blade.php --}}
  2. @extends('layouts.app')
  3. @section('title', '| Users')
  4. @section('content')
  5. <div class="col-lg-10 col-lg-offset-1">
  6. <h1><i class="fa fa-users"></i> User Management
  7. <a href="{{ route('roles.index') }}" class="btn btn-default pull-right">Roles</a>
  8. <a href="{{ route('permissions.index') }}" class="btn btn-default pull-right">Permissions</a>
  9. <a href="{{ route('users.create') }}" class="btn btn-success">Add User</a>
  10. </h1>
  11. <hr>
  12. <div class="table-responsive">
  13. <table class="table table-bordered table-striped">
  14. <thead>
  15. <tr>
  16. <th>Name</th>
  17. <th>Email</th>
  18. <th>Date/Time Added</th>
  19. <th>User Roles</th>
  20. <th>Action</th>
  21. </tr>
  22. </thead>
  23. <tbody>
  24. @foreach ($users as $user)
  25. <tr>
  26. <td>{{ $user->name }}</td>
  27. <td>{{ $user->email }}</td>
  28. <td>{{ $user->created_at->format('F d, Y h:ia') }}</td>
  29. <td>{{ $user->roles()->pluck('name')->implode(' ') }}</td>
  30. <td>
  31. <a href="{{ route('users.edit', $user->id) }}" class="btn btn-warning">Edit</a>
  32. {!! Form::open(['method' => 'DELETE', 'route' => ['users.destroy', $user->id] ]) !!}
  33. {!! Form::submit('Delete', ['class' => 'btn btn-danger']) !!}
  34. {!! Form::close() !!}
  35. </td>
  36. </tr>
  37. @endforeach
  38. </tbody>
  39. </table>
  40. </div>
  41. </div>
  42. @endsection
create.blade.php
  1. {{-- \resources\views\users\create.blade.php --}}
  2. @extends('layouts.app')
  3. @section('title', '| Create User')
  4. @section('content')
  5. <div class='col-lg-4 col-lg-offset-4'>
  6. <h1><i class='fa fa-user-plus'></i> Create User</h1>
  7. <hr>
  8. {!! Form::open(array('url' => 'users')) !!}
  9. <div class="form-group @if ($errors->has('name')) has-error @endif">
  10. {!! Form::label('name', 'Name') !!}
  11. {!! Form::text('name', '', array('class' => 'form-control')) !!}
  12. </div>
  13. <div class="form-group @if ($errors->has('email')) has-error @endif">
  14. {!! Form::label('email', 'Email') !!}
  15. {!! Form::email('email', '', array('class' => 'form-control')) !!}
  16. </div>
  17. <div class="form-group @if ($errors->has('roles')) has-error @endif">
  18. @foreach ($roles as $role)
  19. {!! Form::checkbox('roles[]', $role->id ) !!}
  20. {!! Form::label($role->name, ucfirst($role->name)) !!}<br>
  21. @endforeach
  22. </div>
  23. <div class="form-group @if ($errors->has('password')) has-error @endif">
  24. {!! Form::label('password', 'Password') !!}<br>
  25. {!! Form::password('password', array('class' => 'form-control')) !!}
  26. </div>
  27. <div class="form-group @if ($errors->has('password')) has-error @endif">
  28. {!! Form::label('password', 'Confirm Password') !!}<br>
  29. {!! Form::password('password_confirmation', array('class' => 'form-control')) !!}
  30. </div>
  31. {!! Form::submit('Register', array('class' => 'btn btn-primary')) !!}
  32. {!! Form::close() !!}
  33. </div>
  34. @endsection
edit.blade.php

  1. {{-- \resources\views\users\edit.blade.php --}}
  2. @extends('layouts.app')
  3. @section('title', '| Update User')
  4. @section('content')
  5. <div class='col-lg-4 col-lg-offset-4'>
  6. <h1><i class='fa fa-user-plus'></i> Update {{$user->name}}</h1>
  7. <hr>
  8. {{ Form::model($user, array('route' => array('users.update', $user->id), 'method' => 'PUT')) }}
  9. <div class="form-group @if ($errors->has('name')) has-error @endif">
  10. {{ Form::label('name', 'Name') }}
  11. {{ Form::text('name', null, array('class' => 'form-control')) }}
  12. </div>
  13. <div class="form-group @if ($errors->has('email')) has-error @endif">
  14. {{ Form::label('email', 'Email') }}
  15. {{ Form::email('email', null, array('class' => 'form-control')) }}
  16. </div>
  17. <h5><b>Assign Role</b></h5>
  18. <div class="form-group @if ($errors->has('roles')) has-error @endif">
  19. @foreach ($roles as $role)
  20. {{ Form::checkbox('roles[]', $role->id, $user->roles ) }}
  21. {{ Form::label($role->name, ucfirst($role->name)) }}<br>
  22. @endforeach
  23. </div>
  24. <div class="form-group @if ($errors->has('password')) has-error @endif">
  25. {{ Form::label('password', 'Password') }}<br>
  26. {{ Form::password('password', array('class' => 'form-control')) }}
  27. </div>
  28. <div class="form-group @if ($errors->has('password')) has-error @endif">
  29. {{ Form::label('password', 'Confirm Password') }}<br>
  30. {{ Form::password('password_confirmation', array('class' => 'form-control')) }}
  31. </div>
  32. {{ Form::submit('Update', array('class' => 'btn btn-primary')) }}
  33. {{ Form::close() }}
  34. </div>
  35. @endsection
Role Management Module

Now add following code in RoleController.php to create new role.

RoleController.php

  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Role;
  4. use App\Permission;
  5. use Illuminate\Http\Request;
  6. class RoleController extends Controller
  7. {
  8. public function __construct()
  9. {
  10. $this->middleware('auth');
  11. }
  12. public function index()
  13. {
  14. $roles = Role::all();
  15. return view('roles.index',compact('roles'));
  16. }
  17. /**
  18. * Show the form for creating a new resource.
  19. *
  20. * @return \Illuminate\Http\Response
  21. */
  22. public function create()
  23. {
  24. $permissions = Permission::all();//Get all permissions
  25. return view('roles.create', compact('permissions'));
  26. }
  27. /**
  28. * Store a newly created resource in storage.
  29. *
  30. * @param \Illuminate\Http\Request $request
  31. * @return \Illuminate\Http\Response
  32. */
  33. public function store(Request $request)
  34. {
  35. $this->validate($request, [
  36. 'name'=>'required|unique:roles|max:10',
  37. 'permissions' =>'required',
  38. ]
  39. );
  40. $role = new Role();
  41. $role->name = $request->name;
  42. $role->save();
  43. if($request->permissions <> ''){
  44. $role->permissions()->attach($request->permissions);
  45. }
  46. return redirect()->route('roles.index')->with('success','Roles added successfully');
  47. }
  48. public function edit($id) {
  49. $role = Role::findOrFail($id);
  50. $permissions = Permission::all();
  51. return view('roles.edit', compact('role', 'permissions'));
  52. }
  53. /**
  54. * Update the specified resource in storage.
  55. *
  56. * @param \Illuminate\Http\Request $request
  57. * @param \App\Role $role
  58. * @return \Illuminate\Http\Response
  59. */
  60. public function update(Request $request,$id)
  61. {
  62. $role = Role::findOrFail($id);//Get role with the given id
  63. //Validate name and permission fields
  64. $this->validate($request, [
  65. 'name'=>'required|max:10|unique:roles,name,'.$id,
  66. 'permissions' =>'required',
  67. ]);
  68. $input = $request->except(['permissions']);
  69. $role->fill($input)->save();
  70. if($request->permissions <> ''){
  71. $role->permissions()->sync($request->permissions);
  72. }
  73. return redirect()->route('roles.index')->with('success','Roles updated successfully');
  74. }
  75. /**
  76. * Remove the specified resource from storage.
  77. *
  78. * @param \App\Role $role
  79. * @return \Illuminate\Http\Response
  80. */
  81. public function destroy($id)
  82. {
  83. $role = Role::findOrFail($id);
  84. $role->delete();
  85. return redirect()->route('roles.index')
  86. ->with('success',
  87. 'Role deleted successfully!');
  88. }
  89. }
Role View index.blade.php

  1. @extends('layouts.app')
  2. @section('title', '| Roles')
  3. @section('content')
  4. <div class="col-lg-10 col-lg-offset-1">
  5. <h1><i class="fa fa-key"></i> Roles Management
  6. <a href="{{ route('users.index') }}" class="btn btn-default pull-right">Users</a>
  7. <a href="{{ route('permissions.index') }}" class="btn btn-default pull-right">Permissions</a>
  8. <a href="{{ URL::to('roles/create') }}" class="btn btn-success">Add Role</a>
  9. </h1>
  10. <hr>
  11. <div class="table-responsive">
  12. <table class="table table-bordered table-striped">
  13. <thead>
  14. <tr>
  15. <th>Role</th>
  16. <th>Permissions</th>
  17. <th>Action</th>
  18. </tr>
  19. </thead>
  20. <tbody>
  21. @foreach ($roles as $role)
  22. <tr>
  23. <td>{{ $role->name }}</td>
  24. <td>{{ str_replace(array('[',']','"'),'', $role->permissions()->pluck('name')) }}</td>
  25. <td>
  26. <a href="{{ URL::to('roles/'.$role->id.'/edit') }}" class="btn btn-warning pull-left">Edit</a>
  27. {!! Form::open(['method' => 'DELETE', 'route' => ['roles.destroy', $role->id] ]) !!}
  28. {!! Form::submit('Delete', ['class' => 'btn btn-danger']) !!}
  29. {!! Form::close() !!}
  30. </td>
  31. </tr>
  32. @endforeach
  33. </tbody>
  34. </table>
  35. </div>
  36. </div>
  37. @endsection
create.blade.php

  1. {{-- \resources\views\roles\create.blade.php --}}
  2. @extends('layouts.app')
  3. @section('title', '| Create Role')
  4. @section('content')
  5. <div class='col-lg-4 col-lg-offset-4'>
  6. <h1><i class='fa fa-key'></i> Create Role</h1>
  7. <hr>
  8. {{ Form::open(array('url' => 'roles')) }}
  9. <div class="form-group">
  10. {{ Form::label('name', 'Name') }}
  11. {{ Form::text('name', null, array('class' => 'form-control')) }}
  12. </div>
  13. <h5><b>Assign Permissions</b></h5>
  14. <div class='form-group'>
  15. @foreach ($permissions as $permission)
  16. {{ Form::checkbox('permissions[]', $permission->id ) }}
  17. {{ Form::label($permission->name, ucfirst($permission->name)) }}<br>
  18. @endforeach
  19. </div>
  20. {{ Form::submit('Save', array('class' => 'btn btn-primary')) }}
  21. {{ Form::close() }}
  22. </div>
  23. @endsection
edit.blade.php

  1. @extends('layouts.app')
  2. @section('title', '| Update Role')
  3. @section('content')
  4. <div class='col-md-4 col-md-offset-4'>
  5. <h1><i class='fa fa-key'></i> Update Role: {{$role->name}}</h1>
  6. <hr>
  7. {{ Form::model($role, array('route' => array('roles.update', $role->id), 'method' => 'PUT')) }}
  8. <div class="form-group">
  9. {{ Form::label('name', 'Role Name') }}
  10. {{ Form::text('name', null, array('class' => 'form-control')) }}
  11. </div>
  12. <h3>Assign Permissions</h3>
  13. @foreach ($permissions as $permission)
  14. {{Form::checkbox('permissions[]', $permission->id, $role->permissions ) }}
  15. {{Form::label($permission->name, ucfirst($permission->name)) }}<br>
  16. @endforeach
  17. <br>
  18. {{ Form::submit('Edit', array('class' => 'btn btn-primary')) }}
  19. {{ Form::close() }}
  20. </div>
  21. @endsection
Permission Management Module

Add following code in PermissionController.php.


  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Permission;
  4. use App\Role;
  5. use Illuminate\Http\Request;
  6. class PermissionController extends Controller
  7. {
  8. public function __construct()
  9. {
  10. $this->middleware('auth');
  11. }
  12. public function index()
  13. {
  14. $permissions = Permission::all();
  15. return view('permissions.index',compact('permissions'));
  16. }
  17. /**
  18. * Show the form for creating a new resource.
  19. *
  20. * @return \Illuminate\Http\Response
  21. */
  22. public function create()
  23. {
  24. $roles = Role::get(); //Get all roles
  25. return view('permissions.create',compact('roles'));
  26. }
  27. /**
  28. * Store a newly created resource in storage.
  29. *
  30. * @param \Illuminate\Http\Request $request
  31. * @return \Illuminate\Http\Response
  32. */
  33. public function store(Request $request)
  34. {
  35. $this->validate($request, [
  36. 'name'=>'required|max:40',
  37. ]);
  38. $permission = new Permission();
  39. $permission->name = $request->name;
  40. $permission->save();
  41. if ($request->roles <> '') {
  42. foreach ($request->roles as $key=>$value) {
  43. $role = Role::find($value);
  44. $role->permissions()->attach($permission);
  45. }
  46. }
  47. return redirect()->route('permissions.index')->with('success','Permission added successfully');
  48. }
  49. public function edit(Permission $permission)
  50. {
  51. return view('permissions.edit', compact('permission'));
  52. }
  53. /**
  54. * Update the specified resource in storage.
  55. *
  56. * @param \Illuminate\Http\Request $request
  57. * @param \App\Permission $permission
  58. * @return \Illuminate\Http\Response
  59. */
  60. public function update(Request $request, Permission $permission)
  61. {
  62. $this->validate($request, [
  63. 'name'=>'required',
  64. ]);
  65. $permission->name=$request->name;
  66. $permission->save();
  67. return redirect()->route('permissions.index')
  68. ->with('success',
  69. 'Permission'. $permission->name.' updated!');
  70. }
  71. /**
  72. * Remove the specified resource from storage.
  73. *
  74. * @param \App\Permission $permission
  75. * @return \Illuminate\Http\Response
  76. */
  77. public function destroy(Permission $permission)
  78. {
  79. $permission->delete();
  80. return redirect()->route('permissions.index')
  81. ->with('success',
  82. 'Permission deleted successfully!');
  83. }
  84. }
index.blade.php

  1. {{-- \resources\views\permissions\index.blade.php --}}
  2. @extends('layouts.app')
  3. @section('title', '| Permissions')
  4. @section('content')
  5. <div class="col-md-10 col-md-offset-1">
  6. <h1><i class="fa fa-key"></i>Permissions Management
  7. <a href="{{ route('users.index') }}" class="btn btn-default pull-right">Users</a>
  8. <a href="{{ route('roles.index') }}" class="btn btn-default pull-right">Roles</a>
  9. <a href="{{ URL::to('permissions/create') }}" class="btn btn-success">Add Permission</a>
  10. </h1>
  11. <hr>
  12. <div class="table-responsive">
  13. <table class="table table-bordered table-striped">
  14. <thead>
  15. <tr>
  16. <th>Permissions</th>
  17. <th>Action</th>
  18. </tr>
  19. </thead>
  20. <tbody>
  21. @foreach ($permissions as $permission)
  22. <tr>
  23. <td>{{ $permission->name }}</td>
  24. <td>
  25. <a href="{{ URL::to('permissions/'.$permission->id.'/edit') }}" class="btn btn-warning pull-left">Edit</a>
  26. {!! Form::open(['method' => 'DELETE', 'route' => ['permissions.destroy', $permission->id] ]) !!}
  27. {!! Form::submit('Delete', ['class' => 'btn btn-danger']) !!}
  28. {!! Form::close() !!}
  29. </td>
  30. </tr>
  31. @endforeach
  32. </tbody>
  33. </table>
  34. </div>
  35. </div>
  36. @endsection
create.blade.php

  1. @extends('layouts.app')
  2. @section('title', '| Create Permission')
  3. @section('content')
  4. <div class='col-md-4 col-md-offset-4'>
  5. <h1><i class='fa fa-key'></i> Create New Permission</h1>
  6. <br>
  7. {{ Form::open(array('url' => 'permissions')) }}
  8. <div class="form-group">
  9. {{ Form::label('name', 'Name') }}
  10. {{ Form::text('name', '', array('class' => 'form-control')) }}
  11. </div><br>
  12. @if(!$roles->isEmpty())
  13. <h3>Assign Permission to Roles</h3>
  14. @foreach ($roles as $role)
  15. {{ Form::checkbox('roles[]', $role->id ) }}
  16. {{ Form::label($role->name, ucfirst($role->name)) }}<br>
  17. @endforeach
  18. @endif
  19. <br>
  20. {{ Form::submit('Save', array('class' => 'btn btn-primary')) }}
  21. {{ Form::close() }}
  22. </div>
  23. @endsection
edit.blade.php

  1. @extends('layouts.app')
  2. @section('title', '| Update Permission')
  3. @section('content')
  4. <div class='col-md-4 col-md-offset-4'>
  5. <h1><i class='fa fa-key'></i> Update {{$permission->name}}</h1>
  6. <br>
  7. {{ Form::model($permission, array('route' => array('permissions.update', $permission->id), 'method' => 'PUT')) }}
  8. <div class="form-group">
  9. {{ Form::label('name', 'Permission Name') }}
  10. {{ Form::text('name', null, array('class' => 'form-control')) }}
  11. </div>
  12. <br>
  13. {{ Form::submit('Update', array('class' => 'btn btn-primary')) }}
  14. {{ Form::close() }}
  15. </div>
  16. @endsection
Post Management Module app/Http/Controllers/PostController.php

  1. <?php
  2. namespace App\Http\Controllers;
  3. use App\Post;
  4. use Illuminate\Http\Request;
  5. class PostController extends Controller
  6. {
  7. public function __construct()
  8. {
  9. $this->middleware('auth');
  10. }
  11. public function index()
  12. {
  13. $posts = Post::latest()->paginate(10);
  14. return view('posts.index', compact('posts'));
  15. }
  16. }
Post View

Now create index.blade.php file in resources\views\posts\index.blade.php.

  1. @extends('layouts.app')
  2. @section('content')
  3. <div class="container">
  4. <div class="row">
  5. <div class="col-md-10 col-md-offset-1">
  6. <div class="panel panel-default">
  7. <div class="panel-heading">
  8. <h3>Posts Management</h3>
  9. </div>
  10. <div class="panel-body">
  11. <div class="table-responsive">
  12. <table class="table table-bordered table-striped">
  13. <thead>
  14. <tr>
  15. <th>Title</th>
  16. <th>Body</th>
  17. <th>Action</th>
  18. </tr>
  19. </thead>
  20. <tbody>
  21. @foreach ($posts as $post)
  22. <tr>
  23. <td>{{ $post->title }}</td>
  24. <td>{{ $post->body }}</td>
  25. <td>
  26. @can('editPost')
  27. <a href="{{ route('posts.edit', $post->id) }}" class="btn btn-info pull-left">Edit</a>
  28. @endcan
  29. @can('deletePost')
  30. {!! Form::open(['method' => 'DELETE', 'route' => ['posts.destroy', $post->id] ]) !!}
  31. {!! Form::submit('Delete', ['class' => 'btn btn-danger']) !!}
  32. {!! Form::close() !!}
  33. @endcan
  34. </td>
  35. </tr>
  36. @endforeach
  37. </tbody>
  38. </table>
  39. </div>
  40. </div>
  41. </div>
  42. <div class="text-center">
  43. {!! $posts->render() !!}
  44. </div>
  45. </div>
  46. </div>
  47. </div>
  48. @endsection

That's it..

You can restrict routes for "User" role using middleware.

In middleware, We will authenticate the current user if user has "Admin" role then User will have full access.

Middleware

  1. <?php
  2. namespace App\Http\Middleware;
  3. use Closure;
  4. use Illuminate\Support\Facades\Auth;
  5. class PermissionMiddleware {
  6. public function handle($request, Closure $next) {
  7. if (Auth::user()->hasRole('Admin')) //If user has admin role
  8. {
  9. return $next($request);
  10. }
  11. if (Auth::user()->hasRole('User')) //If user has user role
  12. {
  13. if ($request->is('posts/create'))//If user is creating a post
  14. {
  15. if (!Auth::user()->hasPermissionTo('addPost'))
  16. {
  17. abort('401');
  18. }
  19. else {
  20. return $next($request);
  21. }
  22. }
  23. }
  24. return $next($request);
  25. }
  26. }

Now add the PermissionMiddleware::class to $routeMiddleware property in app/Http/kernel.php :

  1. protected $routeMiddleware = [
  2.     ....
  3.     'has_permission' => \App\Http\Middleware\PermissionMiddleware::class,
  4. ];

In middleware, I redirect to user to 401 custom error page if the user does not have rights to access routes.

401.blade.php

  1. {{-- \resources\views\errors\401.blade.php --}}
  2. @extends('layouts.app')
  3. @section('content')
  4. <div class='col-md-4 col-md-offset-4'>
  5. <h3><center>401<br>
  6. You do not have permission</center></h3>
  7. </div>
  8. @endsection

Now you can set the middleware to route group like this :

  1. Route::group( ['middleware' => ['auth','has_permission']], function() {
  2. });

Phone: (+91) 8800417876
Noida, 201301