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');
To be added...
Requires PHP 8.0 or higher, and Laravel 8.x or higher (currently supporting up to 9.x)
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"
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.
$post->addAccessControl('view', [
[
'class' => \Tanerkay\ModelAcl\Rules\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
.
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 Tanerkay\ModelAcl\Rules\Rule;
class AgeRequirementRule extends Rule
{
public function authorize(?Authenticatable $user, ...$arguments): void
{
$user ??= $this->getUser();
if ($user->date_of_birth->diffInYears() < $arguments[0]) {
throw new \Exception('Not wise enough');
}
}
}
$drink = Drink::where('is_alcoholic', true)->first();
$drink->addAccessControl('buy', [
[
'class' => AgeRequirementRule::class,
'arguments' => 18,
]
]);
// throws exception if user is under 18 years of age
$drink->can('buy');
composer test
- Spatie for making awesome packages, this package leverages
spatie/laravel-package-tools
and is itself derived fromspatie/laravel-activitylog
.