Unlock Your Laravel App's Potential: Mastering Roles & Permissions with InertiaJS in Laravel 12

Author

Kritim Yantra

Jun 12, 2025

Unlock Your Laravel App's Potential: Mastering Roles & Permissions with InertiaJS in Laravel 12

Ever built a sleek Laravel app, only to realize different users need different access levels? Maybe admins should delete posts, editors can draft content, and regular users just view it? Roles and permissions are your solution—and combining them with Laravel 12 and InertiaJS makes implementation smoother than ever. Let’s build this together, step by step!


🔑 Why Bother with Roles & Permissions?

Imagine a library:

  • Librarians (admins) can add/remove books.
  • Members (users) can only borrow.
  • Guests can browse but not borrow.

Without clear rules, chaos reigns! In web apps, roles/permissions:

  • Protect sensitive data
  • Customize user experiences
  • Prevent accidental/malicious actions

🧰 What You’ll Need

  1. Laravel 12 installed (Official docs)
  2. InertiaJS configured with Vue or React
  3. Spatie’s Laravel-Permission package (industry standard)
  4. Basic Laravel & Vue/React knowledge

💡 Never worked with Inertia? Check Laravel’s Inertia starter kit first!


️ Step 1: Install Spatie’s Permission Package

Think of this like adding a security module to your app.
Run:

composer require spatie/laravel-permission

Publish configs/migrations:

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

Migrate your database:

php artisan migrate

👮 Step 2: Define Roles & Permissions

Permissions = Actions (e.g., create-post, delete-user)
Roles = Job Titles (e.g., admin, editor)

Add this to DatabaseSeeder.php:

use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;

public function run() {
    // Create roles
    $admin = Role::create(['name' => 'admin']);
    $editor = Role::create(['name' => 'editor']);
    
    // Create permissions
    $createPost = Permission::create(['name' => 'create-post']);
    $deletePost = Permission::create(['name' => 'delete-post']);
    
    // Assign permissions to roles
    $admin->givePermissionTo([$createPost, $deletePost]);
    $editor->givePermissionTo($createPost);
}

Seed your database:

php artisan db:seed

🧑 Step 3: Assign Roles to Users

Give users their "job titles":

// When creating a user
$user = User::create([...]);
$user->assignRole('editor');

// Or later
$user = User::find(1);
$user->assignRole('admin');

Check permissions in controllers:

public function destroy(Post $post) {
    // Authorize on-the-fly
    $this->authorize('delete-post', $post); 
    
    // Or manually
    if (!auth()->user()->can('delete-post')) {
        abort(403, 'Access denied!');
    }
}

🛡️ Step 4: Protect Server-Side Routes

Lock sensitive routes like a vault:

// routes/web.php
Route::middleware(['auth', 'can:create-post'])->group(function () {
    Route::get('/posts/create', [PostController::class, 'create']);
});

Route::middleware(['auth', 'role:admin'])->group(function () {
    Route::delete('/users/{id}', [UserController::class, 'destroy']);
});

🖥️ Step 5: Sync Permissions to Inertia Frontend

Pass user permissions to Vue/React like a note:
Update app/Http/Middleware/HandleInertiaRequests.php:

public function share(Request $request): array {
    return array_merge(parent::share($request), [
        'auth' => [
            'user' => $request->user() 
                ? $request->user()->load('permissions') 
                : null
        ],
    ]);
}

Now access permissions in frontend via $page.props.auth.user.permissions!


🎨 Step 6: Dynamic UI in Vue/React Components

Show/hide buttons based on permissions:

<template>
  <!-- Hide delete button from non-admins -->
  <button 
    v-if="$page.props.auth.user?.can('delete-post')"
    @click="deletePost(post.id)"
    class="bg-red-500 text-white p-2"
  >
    Delete Post
  </button>

  <!-- Show admin dashboard link only to admins -->
  <NavLink 
    v-if="$page.props.auth.user?.hasRole('admin')" 
    href="/admin-dashboard"
  >
    Admin Panel
  </NavLink>
</template>

Create helper methods in resources/js/app.js:

// For Vue
app.config.globalProperties.$can = (permission) => {
    return Inertia.page.props.auth.user?.permissions?.includes(permission);
}

// Use like: v-if="$can('edit-post')"

🔐 Step 7: Frontend Route Protection (Optional)

Prevent unauthorized page access:

// In Vue/React page components
import { usePage } from '@inertiajs/vue3'

export default {
    mounted() {
        if (!this.$page.props.auth.user?.hasRole('admin')) {
            // Redirect non-admins
            this.$inertia.visit('/dashboard');
        }
    }
}

🎯 Key Takeaways

  1. Spatie’s package handles heavy permission lifting
  2. Always authorize server-side – client checks are for UX only!
  3. Load permissions via Inertia middleware to hydrate frontend
  4. Use v-if/hasRole() for dynamic UI rendering
  5. Permissions > Roles for granular control

🚨 Golden Rule: Server-side validation is NON-NEGOTIABLE for security. Frontend checks are just for usability!


🚀 Your Next Steps

  1. Explore Spatie’s permission docs
  2. Implement permission groups (e.g., post.edit, user.delete)
  3. Add a role management UI (assign roles in your app!)

You’ve just built a foundational security layer! Whether you’re creating a blog or enterprise SaaS, roles/permissions + Laravel 12 + InertiaJS is a game-changer. Questions? Share them below! 👇

Tags

Comments

No comments yet. Be the first to comment!

Please log in to post a comment:

Sign in with Google

Related Posts