25
OH MY! LARAVEL 5.2 GATES, AUTHSERVICEPROVIDERS AND POLICIES

Laravel 5.2 Gates, AuthServiceProvider and Policies

Embed Size (px)

Citation preview

OH MY!

LARAVEL 5.2 GATES, AUTHSERVICEPROVIDERS AND POLICIES

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

THANK YOU!@SNIPEYHEAD