unstoppablecarl / gate-crasher
Safer Laravel superuser auth
Requires
- php: >=5.6.4
- illuminate/config: 5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.*
- illuminate/contracts: 5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.*
- illuminate/support: 5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.*
Requires (Dev)
- illuminate/auth: 5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.*
- phpunit/phpunit: ^5.7 || ^6 || ^7
- satooshi/php-coveralls: ^1.0
- squizlabs/php_codesniffer: ^3.0
Suggests
- unstoppablecarl/arbiter: Manage Laravel User abilities that target Users
This package is not auto-updated.
Last update: 2024-12-08 04:53:16 UTC
README
Safer Laravel superuser auth.
About
Gate Crasher leverages the Laravel Gate::before($beforeCallback)
api to authorize superuser abilities skipping the normal Gate ability/policy functionality.
When Gate::allows()
is called, If the $beforeCallback
returns a non-null result that result will be considered the result of the check.
See https://laravel.com/docs/5.2/authorization
See Illuminate\Auth\Access\Gate::before()
and Illuminate\Contracts\Auth\Access\Gate::before()
in the Laravel framework.
Requirements
- PHP >= 5.5.9
- Laravel >= 5.2
Installation
The preferred method of installation is via Packagist and Composer.
Run the following command to install the package and add it as a requirement to your project's composer.json
:
composer require unstoppablecarl/gate-crasher
Usage
A Gate Crasher instance should be registered within the boot()
method of a service provider.
Minimal gate crasher setup
<?php use Gate; use Illuminate\Contracts\Auth\Access\Gate as GateContract; use Illuminate\Support\ServiceProvider; use UnstoppableCarl\GateCrasher\GateCrasher; class GateCrasherServiceProvider extends ServiceProvider { public function boot(GateContract $gate) { // define a way to identify super users $superUserChecker = function ($user) { return $user->isSuperUser(); }; $gateCrasher = new GateCrasher($superUserChecker); $beforeCallback = function ($user, $ability, $args) use ($gateCrasher) { return $gateCrasher->before($user, $ability, $args); }; // get Gate instance via boot() dependency injection or app() $gate = app(GateContract::class); // set before callback to a Gate instance $gate->before($beforeCallback); // set before callback using facade Gate::before($beforeCallback); // PRO TIP: use `GateCrasher::register()` // to create and set the before callback on a Gate instance for you $gateCrasher->register($gate); } }
The default configuration of a Gate Crasher instance creates the following behavior:
<?php // login a super user $gate = Gate::withUser($mySuperUser); // allows ALL non-policy abilities $gate->allows('foo'); // true // allows ALL non-Super User policy abilities $gate->allows('update', $someUser); // true // denies abilities that target self $gate->allows('delete', $mySuperUser); // denies abilities that target other Super Users (even when logged in as a Super User) $gate->allows('delete', $someOtherSuperUser);
Configuring Abilities
<?php use UnstoppableCarl\GateCrasher\GateCrasher; $superUserChecker = function ($user) { return $user->isSuperUser(); }; // the default result of any ability checks in the given context $contextDefaults = [ // ignored if null, falls back to default Gate::allows() check GateCrasher::SUPER_USER__TARGETING__SELF => null, // deny all abilities from non-super users targeting super users GateCrasher::SUPER_USER__TARGETING__SUPER_USER => false, // deny all abilities from non-super users targeting super users GateCrasher::NON_SUPER_USER__TARGETING__SUPER_USER => false, ]; // the result of specific ability checks in the given context $abilityOverrides = [ // super users can always update but never delete themselves GateCrasher::SUPER_USER__TARGETING__SELF => [ 'update' => true, 'delete' => false, // ... ], // super users can never update or delete other super users GateCrasher::SUPER_USER__TARGETING__SUPER_USER => [ 'update' => false, 'delete' => false, // ... ], // non-super users can never update or delete other super users GateCrasher::NON_SUPER_USER__TARGETING__SUPER_USER => [ // ignored if null, falls back to $contextDefaults then to Gate::allows() check 'view' => null, 'update' => false, 'delete' => false, // ... ], ]; $gateCrasher = new GateCrasher($superUserChecker, $contextDefaults, $abilityOverrides); use Illuminate\Contracts\Auth\Access\Gate as GateContract; $gate = app(GateContract::class); $gateCrasher->register($gate);
Examples
An example service provider is included here:
examples/GateCrasherServiceProvider.php
How It Works
This is an abstract description of how Gate Crasher works. See the source code for exact details.
<?php use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract; Gate::allows('foo', $target); $targetIsUser = $target instanceof AuthenticatableContract; // allow ANY non-Super User target // (target can be a User, another Model, or any other value) if($sourceIsSuperUser && !$targetIsSuperUser){ return true; } // determine the context if($sourceIsSuperUser && $targetIsSuperUser){ $context = GateCrasher::SUPER_USER__TARGETING__SUPER_USER; } else if($sourceIsSuperUser && $targetIsSelf){ $context = GateCrasher::SUPER_USER__TARGETING__SELF; } else if(!$sourceIsSuperUser && $targetIsSuperUser){ $context = GateCrasher::NON_SUPER_USER__TARGETING__SUPER_USER; } // check for non-null ability override $abilityOverrideValue = $abilityOverrides[$context]['foo']; if ($abilityOverrideValue !== null) { return $abilityOverrideValue; } // check for non-null context default $contextDefaultValue = $contextDefaults[$context]; if($contextDefaultValue !== null){ return $contextDefaultValue; } // DEFAULT GATE BEHAVIOR // if a policy is registered for $target use the policy // if an ability callback is registered for 'foo' use the registered callback // return false;
Running the tests
Run Unit Tests
$ composer phpunit
Run Codesniffer (psr-2)
$ composer phpcs
Run both
$ composer test
Contributing
Contributions and Pull Requests welcome!
Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.
Authors
- Carl Olsen - Initial work - Unstoppable Carl
See also the list of contributors who participated in this project.
License
This project is licensed under the MIT License - see the LICENSE.md file for details