tanerkay/laravel-model-acl

Access control based on individual records / models

Installs: 1

Dependents: 0

Suggesters: 0

Security: 0

Stars: 1

Watchers: 1

Forks: 0

Open Issues: 0

pkg:composer/tanerkay/laravel-model-acl

v0.4 2025-03-05 10:42 UTC

This package is auto-updated.

Last update: 2026-01-04 10:28:25 UTC


README

An experiment in model-based access control for Laravel applications.

This was to address a shortcoming or two I found in Laravel policies and gates, though that is no longer the case.

This package allows record-level access control based on custom authorization rules.

This handles cases where you may have many records in a table, but each entity has its own rules for access control. For example, you may have a table of documents, and it's not a simple scenario where a user can edit their own documents, and view all others. Maybe the access of each document has to be set separately, e.g. document X can be edited by Bob & Jane, and viewed by the Staff group; whereas document Y can only be viewed by the Finance team.

Here's a demo of how you can use it:

use Illuminate\Database\Eloquent\Model;
use Tanerkay\ModelAcl\Traits\ModelBasedAccessControl;

class Report extends Model
{
    use ModelBasedAccessControl;
    
    // ...
}

$post->can('view');

Documentation

Installation

composer require tanerkay/laravel-model-acl

You can publish the migration with:

php artisan vendor:publish --provider="Tanerkay\ModelAcl\ModelAclServiceProvider" --tag="model-acl-migrations"
php artisan migrate

You can optionally publish the config file with:

php artisan vendor:publish --provider="Tanerkay\ModelAcl\ModelAclServiceProvider" --tag="model-acl-config"

Assigning access control rules to individual models

The addAccessControl() method can be used to add rules to individual models.

public function addAccessControl(
    string|array $abilities, 
    object|array $ruleDefinitions, 
    ?string $description = null
): void

It accepts:

  • an ability name or list of abilities that can be used in calls to can().
  • an array of rule definitions, each rule definition is an array containing a class string 'class' and an array of arguments 'arguments'.
  • an optional description of the rule, which can be stored in the database alongside the rule definition.

e.g. Restrict a certain post to moderators and admins.

use Tanerkay\ModelAcl\Rules\HasRole;

$post->addAccessControl('view', [
    [
        'class' => HasRole::class,
        'arguments' => ['admin', 'moderator'],
    ]
]);

// throws exception if $user->hasRole(['admin', 'moderator']) doesn't return true
$post->can('view');

The HasRole class assumes your User model has a method hasRole() that accepts a string or an array of strings. You can customize the name of the method using the env key MODEL_ACL_AUTHENTICATABLE_HAS_ROLE.

Creating custom rules

For other rules or logic, you can construct your own Rule class which implements \Tanerkay\ModelAcl\Contracts\RuleContract or which extends the abstract class \Tanerkay\ModelAcl\Rules\Rule.

e.g.

use Illuminate\Support\Arr;
use Tanerkay\ModelAcl\Rules\Rule;
use Tanerkay\ModelAcl\Exceptions\AuthorizationException;

class IpWhitelistRule extends Rule
{
    public function authorize(?Authenticatable $user, $options): void
    {
        $ip = request()->ip();
        $whitelist = Arr::wrap($options['ip_whitelist']);

        if (!in_array($ip, $whitelist)) {
            throw new AuthorizationException('IP address not in whitelist.');
        }
    }
}
$site = Site::query()->create();

$site->addAccessControl('show', [
    [
        'class' => IpWhitelistRule::class,
        'options' => [
            'ip_whitelist' => ['127.0.0.1'],
        ],
    ]
]);

// throws exception if request()->ip() is not in the whitelist
$site->can('show');

Testing

composer test

Thanks

  • Spatie for making awesome packages, this package leverages spatie/laravel-package-tools and is itself derived from spatie/laravel-activitylog.

License

The MIT License (MIT)