Quick Intro
Welcome to this course about Roles and Permissions. There are many ways to implement them in Laravel, so the goal of this course is to cover the most common scenarios, starting from simple ones and finishing with a complex project.
We will cover:
- Gates/Policies
- Popular spatie/laravel-permission package
- Single/multiple Roles per User
- Single/multiple Teams per User
The lessons are quite long. Each lesson contains one full project about Task Management with different roles/permissions logic and with a link to the repository/branch at the end.
Each repository includes automated Pest tests. I want to emphasize how important it is to cover permission logic through tests because it's one of the main security risks for projects, with the most significant consequences if it is not tested properly.
So, let's dive into our first project!
The functionality of a Laravel project may be visible to different roles in various ways. In this lesson, we will start with the most typical one: separate areas.
What I mean is to separate ALL Laravel files by role in their sub-folders: for admin and simple user:
- Separate Controllers
- Separate Blade Views
- Separate URL groups/prefixes/names
- Middleware to check area permissions
Important notice: every lesson in this course will have a repository at the end of the lesson, with automated tests included.
For example, by the end of this first lesson, we will have THIS as a proof that the functions work:
Project Preparation: Task Management System
In this course, our users will manage Tasks like a to-do list.
I deliberately chose a very simple object: we're focusing on roles and permissions here, whatever those users actually use. In real life, you would still need to apply that role-permission logic to your specific projects.
Migration:
Schema::create('tasks', function (Blueprint $table) { $table->id(); $table->string('name'); $table->date('due_date')->nullable(); $table->foreignId('user_id')->nullable()->constrained(); $table->timestamps();});
app/Models/Task.php:
namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory;use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Relations\BelongsTo; class Task extends Model{ use HasFactory; public function user(): BelongsTo { return $this->belongsTo(User::class); }}
Admin/User: with is_admin
Column
We will create the users.is_admin
column for this simple example.
Migration:
Schema::table('users', function (Blueprint $table) { $table->boolean('is_admin')->default(false);});
Also, we added it as a fillable column in the model.
app/Models/User.php:
class User extends Authenticatable{ protected $fillable = [ 'name', 'email', 'password', 'is_admin', ];
We will cover more complex examples later in this course. For now, our goal is to showcase the separated areas.
Separate Controllers
We will use Laravel Breeze as a starter kit for this project. So, we have typical Auth Controllers...