Implementing Role-Based Permissions in Laravel
Certainly! Here's a simplified and easy-to-understand guide on how to implement role-based permissions in a Laravel project.
---
# **Implementing Role-Based Permissions in Laravel**
In this article, we’ll walk through a simple yet powerful way to implement role-based permissions in your Laravel project. This approach allows you to assign different permissions to roles and enforce access control across your application.
### **1. Set Up the Role and Permission Models**
We'll begin by setting up the `Role` and `RolePermission` models. The `Role` model defines user roles (such as admin, editor, etc.), while the `RolePermission` model will store the permissions for each role.
#### Role Model
```php
use Illuminate\Database\Eloquent\Model;
class Role extends Model
{
protected $fillable = ['name'];
}
```
#### RolePermission Model
```php
use Illuminate\Database\Eloquent\Model;
class RolePermission extends Model
{
protected $fillable = ['role_id', 'key', 'value'];
}
```
### **2. Controller for Managing Permissions**
Now let’s create two controller methods: one for displaying the available permissions for a specific role and another for updating the role’s permissions.
#### **Displaying Permissions**
```php
public function permissions($id)
{
$role = Role::findOrFail($id);
$allRoutes = \Illuminate\Support\Facades\Route::getRoutes();
$permissions = [];
foreach ($allRoutes as $route) {
$routeName = $route->getName();
$uri = strtolower(trim($route->uri(), '/'));
if (strpos($uri, 'admin') === 0 && !in_array($routeName, Admin::$EXCLUDED_ROUTES)) {
$permissions[] = [
'url' => $uri,
'name' => $routeName
];
}
}
// Remove duplicates
$permissions = array_unique($permissions, SORT_REGULAR);
return view("admin.roles.permissions", [
'item' => $role,
'permissions' => $permissions
]);
}
```
Here, we load all routes, filter the admin routes, and exclude any routes you don’t want to assign permissions to. The results are passed to the view for display.
#### **Storing Permissions**
```php
public function permissions_store(Request $request, $id)
{
$role = Role::findOrFail($id);
RolePermission::where('role_id', $role->id)->delete();
foreach ($request->except('_token') as $key => $value) {
$key = \Str::replace("__", ".", $key);
$permissionValue = ($value == 'on') ? 1 : 0;
RolePermission::create([
'role_id' => $role->id,
'key' => $key,
'value' => $permissionValue,
]);
}
return redirect()->to(route('admin.role.get'))->with('success', 'Permissions updated successfully.');
}
```
This method saves the new permissions by iterating over the request data and updating the `RolePermission` table.
### **3. Blade View for Managing Permissions**
Next, we’ll create a Blade view to display and manage the permissions for each role. This form allows toggling the permissions and saving them for a specific role.
```php
@extends('admin.layouts.app')
@section('title')
Role Permissions
@endsection
@section('content')
<section>
<div class="container">
<a class="btn btn-warning my-2 " href="{{ route('admin.role.get') }}">Back</a>
<div class="card shadow-sm">
<div class="card-header">
<h2>Permissions for '{{ $item->name }}'</h2>
</div>
<div class="card-body">
<form action="{{ route('admin.role.permissions.store', $item->id) }}" method="post">
@csrf
<div class="row">
@foreach ($
permissions as $permission)
@php
$permission_value = App\Models\RolePermission::where([
'role_id' => $item->id,
'key' => $permission['name'],
])->first()->value ?? 0;
@endphp
<div class="col-md-4 mb-3">
<div class="form-check form-switch">
<input name="{{ Str::replace('.', '__', $permission['name']) }}"
id="{{ Str::replace('.', '__', $permission['name']) }}"
type="checkbox" class="form-check-input"
{{ $permission_value == 1 ? 'checked' : '' }}>
<label for="{{ Str::replace('.', '__', $permission['name']) }}">
{{ Str::title(Str::replace('_', ' ', $permission['url'])) }}
</label>
</div>
</div>
@endforeach
</div>
<hr>
<button class="btn btn-primary" type="submit">Save Permissions</button>
</form>
</div>
</div>
</div>
</section>
@endsection
```
This Blade template generates checkboxes for each permission, allowing you to toggle them on or off and submit the form to update the role’s permissions.
### **4. Middleware for Permission Checking**
Finally, to enforce permissions in your routes, we’ll create middleware that checks whether the authenticated user has the required permissions for a given route.
```php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class AdminMiddleware
{
public function handle(Request $request, Closure $next)
{
$user = Auth::guard('admin')->user();
if (!$user) {
return redirect()->route('admin.view_login');
}
if ($user->role_id != 1) {
$currentRouteName = \Route::currentRouteName();
$hasPermission = RolePermission::where('role_id', $user->role_id)
->where('key', $currentRouteName)
->exists();
if (!$hasPermission) {
return abort(403, 'Unauthorized');
}
}
return $next($request);
}
}
```
This middleware checks the authenticated user’s role and ensures they have permission to access the route. If not, it aborts the request with a 403 error.
### **5. Applying the Middleware**
To apply the middleware to admin routes, add it to your `web.php` file:
```php
Route::middleware(['admin'])->group(function () {
Route::get('/{id}/permissions', [RoleController::class, 'permissions'])->name('role.permissions');
Route::post('/{id}/permissions/store', [RoleController::class, 'permissions_store'])->name('role.permissions.store');
});
```
### **Conclusion**
This approach provides a straightforward way to manage and enforce role-based permissions in your Laravel application. By dynamically fetching routes, defining permissions, and enforcing them through middleware, you ensure that only authorized users can access specific parts of your application.
This method is flexible enough for many applications, and with a bit of customization, it can be tailored to your specific needs!
3 Comments
Justin Case
April 8, 2022 at 7:38 amPatient Comments are a collection of comments submitted by viewers in
response to a question posed by a MedicineNet doctor.
Jemil Akthtan
July 14, 2022Include anecdotal examples of your experience, or things you took notice of that you feel others would find useful.
Justin Case
April 8, 2022 at 7:38 amPatient Comments are a collection of comments submitted by viewers in
response to a question posed by a MedicineNet doctor.