Upload
alison-gianotto
View
1.676
Download
2
Embed Size (px)
Citation preview
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
WHOAMI
▸ Alison Gianotto (aka “snipe”, aka @snipeyhead)
▸ One of the original members of SDPHP ;)
▸ Working with PHP for 15+ years
▸ CTO/Co-Founder of AnySha.re
▸ Founder of Grokability, Inc.
▸ Creator of Snipe-IT and other internet things
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
PROBLEMS THE AUTHSERVICEPROVIDER SOLVES
▸ Much cleaner syntax in blades (@can and @cannot)
▸ One unified place to keep authorization rules
▸ Assumes a user instance. If no user available, it fails to false
▸ Can handle basic authorization (“does the user own this thing?”) or much more sophisticated rules based off your model methods.
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/PROVIDERS/AUTHSERVICEPROVIDER.PHP
publicfunctionboot(GateContract$gate){$this->registerPolicies($gate);
//--------------------------------//BEFOREANYTHINGELSE//--------------------------------$gate->before(function($user,$ability){if($user->superadmin=='1'){returntrue;}});
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
SCENARIO: USER COMMUNITY WEBSITE
▸ users table
▸ communities table with user_id for creator
▸ communities_users pivot table
▸ boolean is_admin
▸ entries table with created_by for creator
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
SCENARIO: USER COMMUNITY WEBSITE: USERS
▸ Users CAN update their own posts
▸ Users CAN delete their own posts
▸ Users CANNOT update other users’ posts
▸ Uses CAN see other posts in a community
▸ … (etc)
▸ Users CAN message other users if they are not blocked
▸ Users CANNOT messages other users if they are blocked
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/PROVIDERS/AUTHSERVICEPROVIDER.PHP
//Checkiftheusercanupdateanentry$gate->define('update-entry',function($user,$entry){return$user->id===$entry->created_by;});
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/USER.PHP (USER MODEL)/***Checksifauserisamemberofacommunity**@paramCommunity$community*@returnboolean*/publicfunctionisMemberOfCommunity($community){return$this->communities()->where('community_id','=',$community->id)->count()>0;}
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/HTTP/ENTRIESCONTROLLER.PHP (VIA GATE FACADE)
publicfunctiongetEdit(Request$request,$id){
if($entry=Entry::find($id)){
if(Gate::denies('update-entry',$entry)){//Youcanreturna403orwhateveryouwanthereabort(403);}
returnview('entries.edit');}
returnredirect()->back()->with('error','Invalidentry.');
}
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/HTTP/ENTRIESCONTROLLER.PHP (VIA USER MODEL)
publicfunctiongetEdit(Request$request,$id){
if($entry=Entry::find($id)){
if($request->user()->cannot('update-entry',$entry)){//Youcouldreturna403responsehere,etc.abort(403);}
returnview('entries.edit');}
returnredirect()->back()->with('error','Invalidentry.');
}
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
RESOURCES/VIEWS/ENTRIES/VIEW.BLADE.PHP
@can('update-entry',$entry)<ahref="{{route('entry.edit.form',$entry->id)}}">Edit</a>@endcan
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/HTTP/ENTRIESCONTROLLER.PHP (VIA FORM REQUEST)
/***Determineiftheuserisauthorizedtomakethisrequest.**@returnbool*/publicfunctionauthorize(){$entryId=$this->route('entry');
returnGate::allows('update',Entry::findOrFail($entryId));}
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
SCENARIO: USER COMMUNITY WEBSITE: COMMUNITY ADMINS
▸ Community admins CAN edit their own community settings
▸ … (etc)
▸ Community admins CAN update user posts
▸ Community admins CAN add/remove users from community
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/USER.PHP (USER MODEL)/***Returnswhetherornottheuserisanadminofacommunity**@paramobject$community*@returnboolean*/publicfunctionisAdminOfCommunity($community){return$this->communities()->where('community_id','=',$community->id)->where('is_admin','=','1')->count()>0;}
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/PROVIDERS/AUTHSERVICEPROVIDER.PHP//Checkiftheusercanjoinacommunity//(theyarenotalreadyamember)$gate->define('join-community',function($user,$community){if(!$user->isMemberOfCommunity($community)){returntrue;}});
//Checkiftheusercanupdatethecommunitysettings//(theyareanadmin)$gate->define('update-community',function($user,$community){if($user->isAdminOfCommunity($community)){returntrue;}});
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
THIS COULD GET OUT OF HAND QUICKLY. ENTER POLICIES.
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
CREATING A POLICY>phpartisanmake:policyEntryPolicyPolicycreatedsuccessfully.
>phpartisanmake:policyCommunityPolicyPolicycreatedsuccessfully.
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/POLICIES/ENTRYPOLICY.PHP<?phpnamespaceApp\Policies;useApp\User;useApp\Entry;useIlluminate\Auth\Access\HandlesAuthorization;
classEntryPolicy{useHandlesAuthorization;
publicfunctionupdate(User$user,Entry$entry){return$user->id===$entry->created_by;}
publicfunctiondelete(User$user,Entry$entry){//etc}}
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/POLICIES/COMMUNITYPOLICY.PHP<?phpnamespaceApp\Policies;useApp\User;useApp\Community;useIlluminate\Auth\Access\HandlesAuthorization;
classCommunityPolicy{useHandlesAuthorization;
publicfunctionupdate(User$user,Community$community){return$user->id===$community->created_by;}
publicfunctiondelete(User$user,Community$community){//etc}}
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/PROVIDERS/AUTHSERVICEPROVIDER.PHP<?php
namespaceApp\Providers;useApp\Policies\EntryPolicy;useApp\Policies\CommunityPolicy;useIlluminate\Contracts\Auth\Access\GateasGateContract;useIlluminate\Foundation\Support\Providers\AuthServiceProviderasServiceProvider;
classAuthServiceProviderextendsServiceProvider{
protected$policies=[Entry::class=>EntryPolicy::class,Community::class=>CommunityPolicy::class,];
/***Registeranyapplicationauthentication/authorizationservices.**@param\Illuminate\Contracts\Auth\Access\Gate$gate*@returnvoid*/publicfunctionboot(GateContract$gate){$this->registerPolicies($gate);}
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
APP/PROVIDERS/AUTHSERVICEPROVIDER.PHP<?php
namespaceApp\Providers;useApp\Policies\EntryPolicy;useApp\Policies\CommunityPolicy;useIlluminate\Contracts\Auth\Access\GateasGateContract;useIlluminate\Foundation\Support\Providers\AuthServiceProviderasServiceProvider;
classAuthServiceProviderextendsServiceProvider{
protected$policies=[Entry::class=>EntryPolicy::class,Community::class=>CommunityPolicy::class,];
/***Registeranyapplicationauthentication/authorizationservices.**@param\Illuminate\Contracts\Auth\Access\Gate$gate*@returnvoid*/publicfunctionboot(GateContract$gate){$this->registerPolicies($gate);}
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
CHECKING POLICIES
▸ Via Gate facade
▸ Via User Model
if(Gate::denies('update',$entry)){//}
if($user->can('update',$entry)){//}
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
CHECKING POLICIES
▸ Via Blade shortcut:
▸ Via Policy Helper:
@can('update',$entry)
@endcan
if(policy($entry)->update($user,$entry)){//}
LARAVEL 5.2 GATES, AUTHSERVICEPROVIDER AND POLICIES
CONCLUSION: THE AUTHSERVICEPROVIDER + POLICIES LETS YOU
▸ Use existing model methods to determine authorization
▸ Group related authorization rules together for maintainability
▸ Use nifty shortcuts in your blades