Site Builder Studio

SITEBUILDERSTUDIO

Granular permissions in Laravel

In the evolving landscape of web applications, a one-size-fits-all approach to permissions often falls short. Many developers are acquainted with Role-Based Access Control (RBAC), where users are designated roles, and these roles are accorded certain permissions. However, for intricate applications that demand a heightened layer of precision, a more tailored approach becomes essential.

Enter Granular Project-Based Permissions—a refined system for access control. It’s designed for applications that demand permissions to be discerned not just by user roles but intricately tailored to specific contexts or projects.

In this tutorial, we’ll utilize a project management system as our foundational example to illustrate the potential of this enhanced permission system. By harnessing the Spatie’s permissions package, coupled with Laravel’s robust Eloquent and the dynamic capabilities of Livewire, we will construct an adaptable permission matrix that evaluates both user permissions and their specific project context.

But remember, while our example centers on a project management paradigm, the essence of this guide is adaptability. Whether your next venture is a niche-specific SaaS, an intricate CRM, or a groundbreaking platform yet to be imagined, the techniques illustrated here can be adjusted and scaled to your unique requirements. Dive in, and discover the potential of truly granular permissions in Laravel.

Granular permissions

This solution integrates Spatie’s permissions for a granular, project-specific permission system. The combination of the Spatie package with this custom relationship allows for both general role/permissions and specific project permissions.


Setup Spatie Permissions

Here’s a list for starters, we’ll add more once the new permissions framework is in place.

create project

read project

update project

delete project

create task

read task

update task

delete task


Create project_user_permission table

1. **Enhance Database Structure**:

– Create a table called `project_user_permission` which will have the columns:

– `user_id`

– `project_id`

– `permission_id`

2. **Migrate the New Structure**:

Create a new migration:

php artisan make:migration create_project_user_permission_table

Inside this migration:

public function up() {

Schema::create(‘project_user_permission’, function (Blueprint $table) {

$table->unsignedBigInteger(‘user_id’);

$table->unsignedBigInteger(‘project_id’);

$table->unsignedBigInteger(‘permission_id’);

$table->foreign(‘user_id’)->references(‘id’)->on(‘users’)->onDelete(‘cascade’);

$table->foreign(‘project_id’)->references(‘id’)->on(‘projects’)->onDelete(‘cascade’);

$table->foreign(‘permission_id’)->references(‘id’)->on(‘permissions’)->onDelete(‘cascade’);

$table->unique([‘user_id’, ‘project_id’, ‘permission_id’]);

});

}


Add Method to User Model

public function hasProjectPermission($permissionName, $project) {

$permissionId = Spatie\Permission\Models\Permission::findByName($permissionName)->id;

return DB::table(‘project_user_permission’)

->where(‘user_id’, $this->id)

->where(‘project_id’, $project->id)

->where(‘permission_id’, $permissionId)

->exists();

}


Checking Permissions

To check if a user has the permission ‘edit tasks’ for a specific project:

$user->hasProjectPermission(‘edit tasks’, $specificProject);

In Blade:

@if($user->hasProjectPermission(‘edit tasks’, $specificProject))

<!– Display the edit button for tasks in that specific project –>

@endif

Managing Permissions

To grant a permission for a user on a specific project:

$permissionId = Spatie\Permission\Models\Permission::findByName(‘edit tasks’)->id;

DB::table(‘project_user_permission’)->insert([

‘user_id’ => $user->id,

‘project_id’ => $specificProject->id,

‘permission_id’ => $permissionId

]);

To revoke a permission:

$permissionId = Spatie\Permission\Models\Permission::findByName(‘edit tasks’)->id;

DB::table(‘project_user_permission’)

->where(‘user_id’, $user->id)

->where(‘project_id’, $specificProject->id)

->where(‘permission_id’, $permissionId)

->delete();


Permissions Management Page

Creating a Livewire page to manage permissions for users within a project will involve a few key steps. We’ll create:

1. A Livewire component to display users associated with a project and manage their permissions.

2. The Blade view for the component.

3. Necessary Livewire methods for interaction.

Let’s break it down step-by-step:

Creating a Livewire page to manage permissions for users within a project will involve a few key steps. We’ll create:

1. A Livewire component to display users associated with a project and manage their permissions.

2. The Blade view for the component.

3. Necessary Livewire methods for interaction.

Let’s break it down step-by-step:

namespace App\Http\Livewire;

use Livewire\Component;

use App\Models\Project;

use App\Models\User;

use Spatie\Permission\Models\Permission;

class ManageProjectPermissions extends Component

{

public $project;

public $permissions;

public $users;

public $selectedUser; // For dropdown selection

public function mount(Project $project) {

$this->project = $project;

$this->permissions = Permission::all();

$this->users = $project->users;

$this->selectedUser = null;

}

public function addUserToProject() {

$user = User::find($this->selectedUser);

$this->project->users()->attach($user);

$this->users = $this->project->users; // Refresh users

}

public function removeUserFromProject($userId) {

$this->project->users()->detach($userId);

$this->users = $this->project->users; // Refresh users

}

public function updateUserPermission($userId, $permissionId, $value) {

$user = $this->users->find($userId);

if($value) {

// Grant permission

DB::table(‘project_user_permission’)->updateOrInsert([

‘user_id’ => $user->id,

‘project_id’ => $this->project->id,

‘permission_id’ => $permissionId

]);

} else {

// Revoke permission

DB::table(‘project_user_permission’)

->where(‘user_id’, $user->id)

->where(‘project_id’, $this->project->id)

->where(‘permission_id’, $permissionId)

->delete();

}

}

public function render() {

return view(‘livewire.manage-project-permissions’);

}

}