composer require imanghafoori/laravel-heyman
PHP > v7.0
Laravel > v5.4
Imagine your boss comes to you and says :
Hey man, When you go to login form, You should be guest, Otherwise you must get redirected to '/panel', Write the code for me, just now... But KEEP IN MIND you are not allowed to touch the current code. it is very sensitive and we do not want you to tamper with it. You may break it.
And you write code like this in a Service Provider boot
method to implement what your boss wanted.
This way you can fully decouple authorization and a lot of guarding code from the rest of your application code and put it in an other place. So your Controllers and Routes become less crowded. and you will have a central place where you limit the access of users to your application.
IDE
Auto-completion
is fully supported.
You can put these codes in
AuthServiceProvider.php
(or any other service provider)boot
method to take effect.
HeyMan::whenYouVisitUrl(['/welcome', '/home'])->... // you can pass an Array
HeyMan::whenYouVisitUrl( '/welcome', '/home' )->... // variable number of args
HeyMan::whenYouVisitUrl('/admin/articles/*')->... // or match by wildcard
HeyMan::whenYouVisitRoute('welcome.name')->...
HeyMan::whenYouVisitRoute('welcome.*')->... // or match by wildcard
HeyMan::whenYouCallAction('HomeController@index')->...
HeyMan::whenYouCallAction('HomeController@*')->... // or match by wildcard
HeyMan::whenYouMakeView('article.editForm')->... // also accepts an array
HeyMan::whenYouMakeView('article.*')->... // You can watch a group of views
HeyMan::whenEventHappens('myEvent')->...
HeyMan::whenYouSave(\App\User::class)->...
HeyMan::whenYouFetch(\App\User::class)->...
HeyMan::whenYouCreate(\App\User::class)->...
HeyMan::whenYouUpdate(\App\User::class)->...
HeyMan::whenYouDelete(\App\User::class)->...
Note that the saving model is passed to the Gate of callback in the next chain call. so for example you can check the ID of the model which is saving.
*In case the gate returns false
an AuthorizationException
will be thrown.
*(If it is not the thing you want, do not worry you can customize the action very easily, we will discuss shortly.)
This way gate is checked after event('myEvent')
is executed any where in our app
HeyMan::whenYouVisitUrl('/home')->thisGateShouldAllow('hasRole', 'param1')->otherwise()->...;
HeyMan::whenYouVisitUrl('/home')->thisGateShouldAllow('SomeClass@someMethod', 'param1')->otherwise()->...;
Passing a Closure as a Gate:
$gate = function($user, $role){
/// some logic
return true;
}
HeyMan::whenYouVisitUrl('/home')->thisGateShouldAllow($gate, 'editor')->otherwise()->...;
HeyMan::whenYouVisitUrl('/home')-> youShouldBeGuest() ->otherwise()->...;
HeyMan::whenYouVisitUrl('/home')-> youShouldBeLoggedIn() ->otherwise()->...;
HeyMan::whenYouVisitUrl('home')->thisMethodShouldAllow('someClass@someMethod', ['param1'])->otherwise()->...;
HeyMan::whenYouVisitUrl('home')->thisClosureShouldAllow(Ω function($a) { ... }, ['param1']) ->otherwise()->...;
HeyMan::whenYouVisitUrl('home')->thisValueShouldAllow(Ω $someValue )->otherwise()->...;
You can also use one of these:
HeyMan::whenYouVisitUrl('home')->youShouldAlways()-> ...
HeyMan::whenYouVisitUrl('home')->sessionShouldHave('key1')->...
HeyMan::whenSaving(\App\User::class)->thisGateShouldAllow('hasRole', 'editor')->otherwise()->weDenyAccess();
An AuthorizationException
will be thrown if needed
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->redirect()->to(...) ->with([...]);
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->redirect()->route(...) ->withErrors(...);
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->redirect()->action(...) ->withInput(...);
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->redirect()->intended(...);
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->redirect()->guest(...);
$msg = 'My Message';
HeyMan::whenYouVisitUrl('/login')
->youShouldBeGuest()
->otherwise()
->throwNew(AuthorizationException::class, $msg);
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->abort(...);
Calling these functions generate exact same response as calling them on the response()
helper function:
return response()->json(...);
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->response()->json(...);
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->response()->view(...);
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->response()->jsonp(...);
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->response()->make(...);
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->response()->download(...);
You may want to call some method or fire an event right before you send the response back.
You can do so by afterCalling()
and afterFiringEvent()
methods.
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->afterFiringEvent('explode')->response()->json(...);
HeyMan::whenYouVisitUrl('/login')-> ... ->otherwise()->afterCalling('someclass@method1')->response()->json(...);
If you find an issue, or have a better way to do something, feel free to open an issue or a pull request. If you use laravel-widgetize in your open source project, create a pull request to provide it's url as a sample application in the README.md file.
If you discover any security related issues, please email imanghafoori1@gmail.com instead of using the issue tracker.
As always if you found this package useful and you want to encourage us to maintain and work on it. Just press the star button to declare your willing.