Skip to content

Instantly share code, notes, and snippets.

@meigwilym
Last active January 31, 2020 14:39
Show Gist options
  • Save meigwilym/623b02bebca76b9b38907d1421e26d34 to your computer and use it in GitHub Desktop.
Save meigwilym/623b02bebca76b9b38907d1421e26d34 to your computer and use it in GitHub Desktop.
Using Bouncer to check abilities

Bouncer to Check Abilities

The seeder file is how abilities and permissions are applied to roles.

In the policy file I use $user->can() to check if an user has an ability.

Each policy was loaded in a controller with $this->authorizeResource(ClientPolicy::class) in the constructor.

Using this pattern lead to a Maximum function nesting level of '500' reached, aborting! error.

The Fix

Create a BouncerProvider and move all the Bouncer::ownedVia() calls to it's boot() method.

Forget about the Policy files.

At the top of each controller, add a __constructor() which calls $this->authoriseResource(Client::class).

That's right, pass the Client class and not the ClientPolicy. Why does this work? I don't know yet, but it does.

<?php
use App\Client;
use App\User;
use App\Site;
use App\Plot;
use App\SalesStatus;
use Silber\Bouncer\BouncerFacade as Bouncer;
use Illuminate\Database\Seeder;
class AbilitySeeder extends Seeder
{
/**
* Run the database seeds.
*
* @return void
*/
public function run()
{
Bouncer::allow('superadmin')->everything();
// futurium admins can do everything APART from create superadmins
Bouncer::allow('futurium-admin')->everything();
Bouncer::forbid('futurium-admin')->to('make-superadmin', User::class);
// Clients
Bouncer::ownedVia(Client::class, function ($client, $user) {
return $client->id === $user->client->id;
});
Bouncer::allow('client-admin')->toOwn(Client::class)->to(['view', 'update']);
Bouncer::allow('client-user')->to('view', Client::class);
// Users
Bouncer::ownedVia(User::class, function ($user, $model) {
return $user->client->id === $model->client->id;
});
Bouncer::allow('client-admin')->toOwn(User::class);
// Sites
Bouncer::ownedVia(Site::class, function ($site, $user) {
return $site->client->id === $user->client->id;
});
Bouncer::allow('client-user')->toOwn(Site::class)->to(['view', 'update']);
Bouncer::allow('client-admin')->toOwn(Site::class);
// Plots
Bouncer::ownedVia(Plot::class, function ($plot, $user) {
return $plot->site->client->id === $user->client->id;
});
Bouncer::allow('client-user')->toOwn(Plot::class);
Bouncer::allow('client-admin')->toOwn(Plot::class);
// Sales Statuses
Bouncer::ownedVia(SalesStatus::class, function ($status, $user) {
return $status->client->id === $user->client->id;
});
Bouncer::allow('client-user')->to('view', SalesStatus::class);
Bouncer::allow('client-admin')->toOwn(SalesStatus::class);
}
}
<?php
namespace App\Policies;
use App\User;
use App\Client;
use Illuminate\Auth\Access\HandlesAuthorization;
class ClientPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view any clients.
*
* @param \App\User $user
* @return mixed
*/
public function viewAny(User $user): bool
{
return $user->can('view', Client::class);
}
/**
* Determine whether the user can view the client.
*
* @param \App\User $user
* @param \App\Client $client
* @return mixed
*/
public function view(User $user, Client $client): bool
{
return $user->can('view', $client);
}
/**
* Determine whether the user can create clients.
*
* @param \App\User $user
* @return mixed
*/
public function create(User $user): bool
{
return $user->can('create', Client::class);
}
/**
* Determine whether the user can update the client.
*
* @param \App\User $user
* @param \App\Client $client
* @return mixed
*/
public function update(User $user, Client $client): bool
{
return $user->can('update', $client);
}
/**
* Determine whether the user can delete the client.
*
* @param \App\User $user
* @param \App\Client $client
* @return mixed
*/
public function delete(User $user, Client $client): bool
{
return $user->can('delete', $client);
}
/**
* Determine whether the user can restore the client.
*
* @param \App\User $user
* @param \App\Client $client
* @return mixed
*/
public function restore(User $user, Client $client): bool
{
return $user->can('restore', $client);
}
/**
* Determine whether the user can permanently delete the client.
*
* @param \App\User $user
* @param \App\Client $client
* @return mixed
*/
public function forceDelete(User $user, Client $client): bool
{
return $user->can('forceDelete', $client);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment