Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Nova Permission Laravel Package

insenseanalytics/laravel-nova-permission

Nova tool for managing roles and permissions in Laravel Nova, built on spatie/laravel-permission. Adds permission and role resources to Nova with a familiar UI, letting admins create, assign, and organise access control without leaving the dashboard.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install both packages — the tool is a Nova UI on top of Spatie, it does not replace it:
    composer require spatie/laravel-permission insenseanalytics/laravel-nova-permission
    php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
    php artisan migrate
    
  2. Publish and read the config first — this is where 80% of the behavior lives:
    php artisan vendor:publish --tag=nova-permission-config
    
    Skim config/nova-permission.php for the model/table mappings and guard settings before writing any code. Mismatches here are the #1 source of "roles don't show up".
  3. Register the tool in app/Providers/NovaServiceProvider.php:
    public function tools()
    {
        return [
            new \Insenseanalytics\LaravelNovaPermission\LaravelNovaPermission,
        ];
    }
    
  4. Wire roles into a resource so admins can assign them from the detail view:
    use Insenseanalytics\LaravelNovaPermission\RoleSelect;
    
    public function fields(Request $request)
    {
        return [
            ID::make()->sortable(),
            Text::make('Name'),
            RoleSelect::make('Roles', 'roles')
                ->options(Role::where('guard_name', 'web')->pluck('name', 'id')),
        ];
    }
    
  5. First use case to validate the setup: log in as a Nova user, open the Permissions tool in the sidebar, create a editor role, tick a few permissions, then assign it to yourself via the RoleSelect field on your user detail page and confirm a $user->can('...') gate returns true. If that loop works end-to-end, the package is correctly installed.

Where to look when things misbehave: the tool's config file, then the package's src/ (resources are typically plain Nova resources registered by the tool, so you can trace the field/property names), then Spatie's permission.php.

Implementation Patterns

Bootstrap permissions in code, manage them in the UI. The tool is great for granting roles to individual users and tweaking permission sets, but treat roles/permissions themselves as seed data so environments stay reproducible:

// database/seeders/PermissionSeeder.php
foreach (['posts.view', 'posts.create', 'posts.publish'] as $name) {
    Permission::firstOrCreate(['name' => $name, 'guard_name' => 'web']);
}
$editor = Role::firstOrCreate(['name' => 'editor', 'guard_name' => 'web']);
$editor->syncPermissions(['posts.view', 'posts.create']);

The UI-created permissions will be silently absent from staging/prod until you add them to the seeder — this is the single most common drift problem with permission UIs.

Keep the RoleSelect field guarded. Don't let non-admins edit roles just because the field is on the form:

RoleSelect::make('Roles')
    ->canSee(fn (Request $request) => $request->user()->hasRole('admin'))
    ->options(Role::where('guard_name', 'web')->pluck('name', 'id')),

Align gates with Nova visibility. Rather than duplicating permission logic, drive Nova's canSee / authorize from the same Spatie permissions so the UI and the app agree:

public function authorize(Request $request)
{
    return $request->user()->hasPermissionTo('roles.manage');
}

Add a Gate::before super-admin bypass in AuthServiceProvider so admins don't need every permission explicitly.

Multi-guard setups need explicit options. If you have web and api guards, filter RoleSelect options by guard and make sure the user model has Spatie's HasRoles trait with the correct $guard_name. The tool's config lets you point at custom Role/Permission models — if you subclass them, update the config and re-register any resources the tool expects.

Cache invalidation as a habit. Spatie caches the permission map. After any UI change that should propagate to long-running processes (Horizon workers, etc.), run:

php artisan permission:cache-reset

or forget the spatie.permission.cache key in your deployment step.

Authorize the tool, not just the resources. Restrict the tool itself in NovaServiceProvider::tools() with ->canSee(...) so operators without permission-management rights never see the sidebar entry.

Gotchas and Tips

  • The package is effectively unmaintained. Last release was October 2020, which means it targets Nova 2/3 and Laravel 8-era dependencies. On Nova 4+ (Vue 3) the tool's frontend bundle will not load — the sidebar entry simply won't render or will 404 on assets. Verify against your Nova version before committing; if you're on Nova 4/5, plan to fork the Vue components or switch to vyuldashev/nova-permission, which has kept pace.
  • Guard mismatch errors. Spatie throws GuardDoesNotMatch when you assign a web role to an api user. In a mixed-guard app this is common and the tool will surface it as a 500 on save. Make the guard a first-class config decision and filter RoleSelect options by guard_name.
  • Config is not auto-published on some installs. If the tool renders but roles are empty, check that config/nova-permission.php exists and the models/tables keys match your actual schema (especially if you renamed tables via Spatie's config).
  • The config file and the Spatie config can drift. You now have two config files describing the same models. Keep them in sync; a custom Role model declared in one but not the other produces confusing empty dropdowns.
  • Deleting roles is destructive. A role removed through the UI detaches from users (or hits an FK constraint depending on your migration). Snapshot roles before bulk editing in production, and consider DB::transaction around scripted role changes.
  • N+1 on user listings. RoleSelect and role badges on a Nova index will lazy-load roles per row. Add $user->load('roles') or a with('roles') in the resource's indexQuery if the table gets slow.
  • Extension point is the config, not the views. Because the package is old, don't fight its Vue components — override behavior by swapping models in config, adding your own Nova resources alongside, or forking. Copying the package into nova-components/ is often cheaper than patching a stale dependency.
  • Debugging tip: when a permission check fails but the UI shows the role assigned, run php artisan tinker and inspect $user->getRoleNames() and $user->getAllPermissions(). That distinguishes "role not actually attached" (guard or cache) from "gate not wired" (policy/Gate::before), which are the two failure modes the UI masks equally well.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource