Weave Code
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

Bouncer Laravel Package

silber/bouncer

Bouncer adds roles and abilities to Laravel with a fluent, Eloquent-powered API. Define permissions, assign roles to users, and authorize actions via gates and middleware. Supports caching, scoped abilities, and a simple, expressive permission model.

View on GitHub
Deep Wiki
Context7
## Getting Started

### Minimal Setup
1. **Installation**:
   ```bash
   composer require silber/bouncer

Publish the migration and config:

php artisan vendor:publish --provider="Bouncer\BouncerServiceProvider"
php artisan migrate
  1. First Use Case: Define a role and assign it to a user:

    use Bouncer;
    
    // Create a role
    $adminRole = Bouncer::role()->create(['name' => 'admin']);
    
    // Assign the role to a user
    $user = User::find(1);
    $user->assign($adminRole);
    
    // Grant an ability to the role
    $adminRole->allowTo('view', Post::class);
    
  2. Check Permissions:

    if (Bouncer::can($user, 'view', Post::class)) {
        // User can view posts
    }
    

Key Files to Review

  • config/bouncer.php: Configuration for caching, models, and behavior.
  • database/migrations/..._create_bouncer_tables.php: Understand the schema (roles, abilities, and their relationships).
  • app/Providers/BouncerServiceProvider.php: Service provider for customizations.

Implementation Patterns

Core Workflows

1. Role-Based Access Control (RBAC)

  • Define Roles:
    $adminRole = Bouncer::role()->create(['name' => 'admin']);
    $editorRole = Bouncer::role()->create(['name' => 'editor']);
    
  • Assign Roles to Users:
    $user->assign($adminRole);
    $user->assign($editorRole);
    
  • Grant Abilities to Roles:
    $adminRole->allowTo('delete', Post::class);
    $editorRole->allowTo('update', Post::class);
    

2. Direct Ability Assignment

  • Grant abilities directly to users (bypassing roles):
    Bouncer::allow($user)->to('publish', Post::class);
    
  • Revoke abilities:
    Bouncer::forbid($user)->to('publish', Post::class);
    

3. Global Abilities (Everyone)

  • Grant abilities to all users without individual assignments:
    Bouncer::allowEveryone()->to('view', Post::class);
    

4. Multi-Tenancy Support

  • Scope abilities to a tenant:
    Bouncer::scope()->to($tenantId, function () {
        $tenantAdmin = Bouncer::role()->create(['name' => 'tenant_admin']);
        $tenantAdmin->allowTo('manage', TenantPost::class);
    });
    
  • Temporarily override the scope:
    Bouncer::scope()->onceTo($otherTenantId, function () {
        // Queries here use $otherTenantId
    });
    

5. Policy Integration

  • Configure Bouncer to run after policies (default in v1.0+):
    // No config needed; Bouncer runs after policies by default.
    // To revert (e.g., for legacy code):
    Bouncer::runBeforePolicies();
    
  • Example policy interaction:
    class PostPolicy {
        public function delete(User $user, Post $post) {
            return $post->isPublished(); // Policy overrides Bouncer if false
        }
    }
    

6. Dynamic Checks

  • Use canAny() to check if a user has any of multiple abilities:
    if (Bouncer::canAny($user, ['view', 'update'], Post::class)) {
        // User can view or update
    }
    

Integration Tips

Middleware for Authorization

  • Create middleware to check permissions:
    public function handle(Request $request, Closure $next) {
        if (!Bouncer::can($request->user(), 'edit', Post::class)) {
            abort(403);
        }
        return $next($request);
    }
    
  • Apply to routes:
    Route::middleware(['auth', 'can:edit,post'])->group(function () {
        // Protected routes
    });
    

API Gatekeeper

  • Use in API controllers:
    public function update(Request $request, Post $post) {
        $this->authorize('update', $post); // Laravel policy
        if (!Bouncer::can($request->user(), 'update', Post::class)) {
            return response()->json(['error' => 'Unauthorized'], 403);
        }
        // Proceed
    }
    

Seeding Roles and Abilities

  • Seed initial roles/abilities in DatabaseSeeder:
    public function run() {
        $adminRole = Bouncer::role()->create(['name' => 'admin']);
        $adminRole->allowTo(['view', 'create', 'update', 'delete'], Post::class);
        $adminRole->allowTo(['manage'], User::class);
    
        $user = User::first();
        $user->assign($adminRole);
    }
    

Custom Models

  • Extend Bouncer models (e.g., for soft deletes):
    class CustomRole extends \Bouncer\Role {
        use \Illuminate\Database\Eloquent\SoftDeletes;
    }
    Bouncer::useRoleModel(CustomRole::class);
    

Caching

  • Enable caching for performance (default: file):
    'cache' => [
        'driver' => 'redis', // or 'file', 'database'
        'ttl' => 60, // Cache TTL in minutes
    ],
    
  • Clear cache manually:
    Bouncer::refresh();
    

Gotchas and Tips

Pitfalls and Debugging

1. Permission Leaks in Multi-Tenancy

  • Issue: Abilities granted in a tenant scope may leak into the global scope.
  • Fix: Use Bouncer::scope()->to($tenantId, ...) to explicitly scope operations. Avoid mixing global and scoped grants.
  • Debug: Check bouncer_permissions table for unexpected entity_id/entity_type values.

2. Policy Precedence

  • Issue: Bouncer runs after policies by default (v1.0+). If a policy denies access, Bouncer won’t run.
  • Fix: Use Bouncer::runBeforePolicies() if you need Bouncer to override policies.
  • Debug: Test with dd(Bouncer::can($user, 'action', Model::class)) to see evaluation order.

3. Soft Deletes

  • Issue: Soft-deleted roles/abilities may still appear in checks.
  • Fix: Use Bouncer::role()->where(...)->withTrashed()->get() or explicitly restore:
    $role = Bouncer::role()->findOrFail($id)->restore();
    
  • Debug: Run Bouncer::role()->withTrashed()->get() to inspect soft-deleted roles.

4. Morph Map Conflicts

  • Issue: Custom models not registered in the morph map may cause entity_type mismatches.
  • Fix: Register models manually:
    \Illuminate\Database\Eloquent\Model::morphMap([
        'custom_role' => \App\Models\CustomRole::class,
    ]);
    
  • Debug: Check entity_type in bouncer_permissions for unexpected values.

5. Cache Invalidation

  • Issue: Changes to roles/abilities aren’t reflected due to caching.
  • Fix: Clear cache after bulk operations:
    Bouncer::refresh();
    
  • Debug: Temporarily disable caching ('cache' => ['driver' => null]) to test.

6. Global Abilities Overlap

  • Issue: allowEveryone() may unintentionally override scoped abilities.
  • Fix: Prefer scoped grants for tenant-specific permissions. Use allowEveryone() sparingly for truly global actions (e.g., "view public posts").

7. Laravel Policy Conflicts

  • Issue: Policies and Bouncer may conflict if both define the same check.
  • Fix: Use Bouncer::runBeforePolicies() or Bouncer::runAfterPolicies() explicitly. Document which system handles which checks.

Configuration Quirks

1. Table Prefixes

  • Issue: Bouncer tables may not be prefixed correctly.
  • Fix: Configure in config/bouncer.php:
    'tables' => [
        'permissions' => 'bouncer_permissions',
        'roles' => 'bouncer_roles',
    ],
    
  • Debug: Verify table names in `
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.
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium
sandermuller/package-boost-laravel
sandermuller/boost-skills
redaxo/core
yusufgenc/filament-api-forge
l3aro/rating-star-for-filament
leek/filament-subtenant-scope