Skip to content

Commit

Permalink
Update the namespace and add interactive facade (#5)
Browse files Browse the repository at this point in the history
* Add RBAC package registration and service binding

* Refactor rbacContainsDuplicateAbilities method signature

* Add test for throwing duplicate permission exception

* Update composer.json with Laravel 11 enum-backed RBAC

* Update namespace from BinaryCats\Rbac to BinaryCats\LaravelRbac

* Enhance Laravel 11 with opinionated extension

* Apply fixes from StyleCI

---------

Co-authored-by: StyleCI Bot <bot@styleci.io>
  • Loading branch information
cyrillkalita and StyleCIBot authored Mar 20, 2024
1 parent 692631d commit c119629
Show file tree
Hide file tree
Showing 37 changed files with 277 additions and 101 deletions.
2 changes: 1 addition & 1 deletion .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
blank_issues_enabled: false
blank_issues_enabled: true
contact_links:
- name: Ask a question
url: https://github.com/Binary Cats/rbac/discussions/new?category=q-a
Expand Down
39 changes: 30 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
[![run-tests](https://github.com/binary-cats/rbac/actions/workflows/run-tests.yml/badge.svg)](https://github.com/binary-cats/rbac/actions/workflows/run-tests.yml)
[![GitHub Code Style Action Status](https://github.styleci.io/repos/773171043/shield?branch=main&style=flat-square)](https://github.com/binary-cats/rbac/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amain)

Opinionated extension for [spatie/laravel-permissions](https://spatie.be/docs/laravel-permission/v6/introduction).
When your permission list grows and maintenance becomes an issue, this package offers simple way of defining roles and their permissions.
Enhance Laravel 11 with opinionated extension for [spatie/laravel-permissions](https://spatie.be/docs/laravel-permission/v6/introduction).
Before your permission list grows and maintenance becomes an issue, this package offers simple way of defining roles and their permissions.

## Installation

You can install the package via composer:

```bash
composer require binary-cats/rbac
composer require binary-cats/laravel-rbac
```

You can publish the config file with:
Expand All @@ -35,9 +35,9 @@ return [
*/

'jobs' => [
\BinaryCats\Rbac\Jobs\FlushPermissionCache::class,
\BinaryCats\Rbac\Jobs\ResetPermissions::class,
\BinaryCats\Rbac\Jobs\SyncDefinedRoles::class,
\BinaryCats\LaravelRbac\Jobs\FlushPermissionCache::class,
\BinaryCats\LaravelRbac\Jobs\ResetPermissions::class,
\BinaryCats\LaravelRbac\Jobs\SyncDefinedRoles::class,
],

/*
Expand Down Expand Up @@ -74,7 +74,13 @@ php artisan rbac:reset
In a simple setup we usually have two basic parts of an RBAC: a permission and a role.
Permissions are usually grouped by functional or business logic domain and a Role encapsulates them for a specific guard.

To avoid collision with `spatie/laravel-permission` we are going to use `BackedEnum` Ability to hold out enumerated permissions:
1. [Create Abilities](#abilities)
2. [Define Roles](#defined-roles)
3. [Connect the dots](#connect-the-dots)

### Abilities

To avoid collision with `spatie/laravel-permission` we are going to use `BackedEnum` Ability enums to hold out enumerated permissions:
You can read more on using `enums` as permissions at the [official docs](https://spatie.be/docs/laravel-permission/v6/basic-usage/enums).

To create an Ability:
Expand Down Expand Up @@ -111,7 +117,7 @@ php artisan make:role EditorRole
This will generate an `EditorRole` within `App\Roles`:

```php
use BinaryCats\Rbac\DefinedRole;
use BinaryCats\LaravelRbac\DefinedRole;

class EditorRole extends DefinedRole
{
Expand All @@ -136,8 +142,10 @@ This class contains a (now testable!) configuration definition for the role and
We can now adjust it like so:

```php
namespace App\Roles;

use App\Abilities\PostAbility;
use BinaryCats\Rbac\DefinedRole;
use BinaryCats\LaravelRbac\DefinedRole;

class EditorRole extends DefinedRole
{
Expand All @@ -163,6 +171,19 @@ class EditorRole extends DefinedRole
```
Now you are confident a specific role has specific permissions!

### Connect the dots

Now that we have the abilities and roles, simply register role with `rbac.php` config:

```php
'roles' => [
\App\Roles\EditorRole::class,
...
],
```

When you run `rbac:reset` next time, your RBAC will be reset automatically.

## Integration

I suggest adding the script to `post-autoload-dump` of your `composer.json` to make sure the RBAC is reset on every composer dump:
Expand Down
19 changes: 11 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
{
"name": "binary-cats/rbac",
"description": "Enum-backed RBAC extension of spatie/laravel-permission",
"name": "binary-cats/laravel-rbac",
"description": "Laravel 11 enum-backed RBAC extension of spatie/laravel-permission",
"keywords": [
"binary-cats",
"enum",
"laravel",
"rbac"
],
"homepage": "https://github.com/binary-cats/rbac",
"homepage": "https://github.com/binary-cats/laravel-rbac",
"license": "MIT",
"authors": [
{
Expand All @@ -31,15 +31,18 @@
},
"autoload": {
"psr-4": {
"BinaryCats\\Rbac\\": "src/",
"BinaryCats\\Rbac\\Database\\Factories\\": "database/factories/"
"BinaryCats\\LaravelRbac\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"BinaryCats\\Rbac\\Tests\\": "tests/"
"BinaryCats\\LaravelRbac\\Tests\\": "tests/"
}
},
"suggest": {
"binary-cats/laravel-mailgun-webhooks": "Handle Mailgun webhooks in your Laravel application",
"binary-cats/laravel-sku": "Generate SKUs for Eloquent models"
},
"scripts": {
"test": "vendor/bin/phpunit"
},
Expand All @@ -49,10 +52,10 @@
"extra": {
"laravel": {
"providers": [
"BinaryCats\\Rbac\\RbacServiceProvider"
"BinaryCats\\LaravelRbac\\RbacServiceProvider"
],
"aliases": {
"Rbac": "BinaryCats\\Rbac\\Facades\\Rbac"
"Rbac": "BinaryCats\\LaravelRbac\\Facades\\Rbac"
}
},
"branch-alias": {
Expand Down
8 changes: 3 additions & 5 deletions config/rbac.php
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
<?php

use App\Enums\Ability;

return [

/*
Expand All @@ -14,9 +12,9 @@
*/

'jobs' => [
\BinaryCats\Rbac\Jobs\FlushPermissionCache::class,
\BinaryCats\Rbac\Jobs\ResetPermissions::class,
\BinaryCats\Rbac\Jobs\SyncDefinedRoles::class,
\BinaryCats\LaravelRbac\Jobs\FlushPermissionCache::class,
\BinaryCats\LaravelRbac\Jobs\ResetPermissions::class,
\BinaryCats\LaravelRbac\Jobs\SyncDefinedRoles::class,
],

/*
Expand Down
2 changes: 1 addition & 1 deletion src/Actions/StorePermission.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace BinaryCats\Rbac\Actions;
namespace BinaryCats\LaravelRbac\Actions;

use BackedEnum;
use Illuminate\Support\Facades\Artisan;
Expand Down
2 changes: 1 addition & 1 deletion src/Actions/SyncDefinedRole.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace BinaryCats\Rbac\Actions;
namespace BinaryCats\LaravelRbac\Actions;

use BackedEnum;
use Illuminate\Support\Facades\Artisan;
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/AbilityMakeCommand.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace BinaryCats\Rbac\Commands;
namespace BinaryCats\LaravelRbac\Commands;

use Illuminate\Console\Concerns\CreatesMatchingTest;
use Illuminate\Console\GeneratorCommand;
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/DefinedRoleMakeCommand.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace BinaryCats\Rbac\Commands;
namespace BinaryCats\LaravelRbac\Commands;

use Illuminate\Console\Concerns\CreatesMatchingTest;
use Illuminate\Console\GeneratorCommand;
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/RbacResetCommand.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace BinaryCats\Rbac\Commands;
namespace BinaryCats\LaravelRbac\Commands;

use Illuminate\Console\Command;
use Illuminate\Support\Collection;
Expand Down
2 changes: 1 addition & 1 deletion src/Contracts/DefinedRole.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace BinaryCats\Rbac\Contracts;
namespace BinaryCats\LaravelRbac\Contracts;

interface DefinedRole
{
Expand Down
6 changes: 3 additions & 3 deletions src/DefinedRole.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<?php

namespace BinaryCats\Rbac;
namespace BinaryCats\LaravelRbac;

use BinaryCats\Rbac\Actions\SyncDefinedRole;
use BinaryCats\Rbac\Contracts\DefinedRole as DefinedRoleContract;
use BinaryCats\LaravelRbac\Actions\SyncDefinedRole;
use BinaryCats\LaravelRbac\Contracts\DefinedRole as DefinedRoleContract;
use Illuminate\Support\Str;
use ReflectionClass;

Expand Down
4 changes: 2 additions & 2 deletions src/DiscoverAbilities.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php

namespace BinaryCats\Rbac;
namespace BinaryCats\LaravelRbac;

use BinaryCats\Rbac\Exceptions\RbacException;
use BinaryCats\LaravelRbac\Exceptions\RbacException;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use ReflectionClass;
Expand Down
19 changes: 15 additions & 4 deletions src/Exceptions/RbacException.php
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
<?php

namespace BinaryCats\Rbac\Exceptions;
namespace BinaryCats\LaravelRbac\Exceptions;

use BackedEnum;
use Exception;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;

class RbacException extends Exception
{
public static function rbacContainsDuplicateAbilities($abilities): static
/**
* @param \Illuminate\Support\Collection $abilities
*
* @return static
*/
public static function rbacContainsDuplicateAbilities(Collection $abilities): static
{
$duplicates = $abilities
->groupBy('value')
->filter(fn ($element) => $element->count() > 2)
->map(fn (BackedEnum $enum) => Str::of(get_class($enum))->append(':', $enum->value));
->filter(fn ($element) => $element->count() > 1)
->collapse()
->map(
fn (BackedEnum $enum) => Str::of(get_class($enum))
->classBasename()
->append(':', $enum->value)
);

$message = __('The following RBAC abilities are duplicated [:duplicates]', [
'duplicates' => $duplicates->implode(', '),
Expand Down
13 changes: 13 additions & 0 deletions src/Facades/Rbac.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?php

namespace BinaryCats\LaravelRbac\Facades;

use Illuminate\Support\Facades\Facade;

class Rbac extends Facade
{
protected static function getFacadeAccessor()
{
return \BinaryCats\LaravelRbac\Rbac::class;
}
}
2 changes: 1 addition & 1 deletion src/Jobs/FlushPermissionCache.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace BinaryCats\Rbac\Jobs;
namespace BinaryCats\LaravelRbac\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Foundation\Bus\Dispatchable;
Expand Down
13 changes: 4 additions & 9 deletions src/Jobs/ResetPermissions.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
<?php

namespace BinaryCats\Rbac\Jobs;
namespace BinaryCats\LaravelRbac\Jobs;

use BackedEnum;
use BinaryCats\Rbac\Actions\StorePermission;
use BinaryCats\Rbac\DiscoverAbilities;
use BinaryCats\LaravelRbac\Actions\StorePermission;
use BinaryCats\LaravelRbac\Facades\Rbac;
use Illuminate\Bus\Queueable;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
Expand All @@ -19,14 +19,12 @@ class ResetPermissions
use SerializesModels;

protected string $guard;
protected string $abilityPath;

/**
* @param string|null $guard
*/
public function __construct(string $guard = null)
{
$this->abilityPath = config('rbac.path');
$this->guard = $guard ?? config('auth.defaults.guard');
}

Expand All @@ -44,9 +42,6 @@ public function handle(): void
*/
protected function permissions(): Collection
{
return DiscoverAbilities::within(
abilitiesPath: $this->abilityPath,
basePath: app()->basePath()
);
return Rbac::abilities();
}
}
4 changes: 2 additions & 2 deletions src/Jobs/SyncDefinedRoles.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?php

namespace BinaryCats\Rbac\Jobs;
namespace BinaryCats\LaravelRbac\Jobs;

use BinaryCats\Rbac\Contracts\DefinedRole;
use BinaryCats\LaravelRbac\Contracts\DefinedRole;
use Illuminate\Bus\Queueable;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
Expand Down
50 changes: 50 additions & 0 deletions src/Rbac.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php

namespace BinaryCats\LaravelRbac;

use Illuminate\Support\Collection;

class Rbac
{
/** @var string */
protected string $abilitiesPath;

/** @var string */
protected string $basePath;

/** @var \Illuminate\Support\Collection|null */
protected ?Collection $abilities = null;

/**
* @param string $abilitiesPath
* @param string $basePath
*/
public function __construct(string $abilitiesPath, string $basePath)
{
$this->abilitiesPath = $abilitiesPath;
$this->basePath = $basePath;
}

/**
* Return the list of all abilities in the application.
*/
public function abilities(): Collection
{
if (null === $this->abilities) {
$this->abilities = $this->discoverAbilities();
}

return $this->abilities;
}

/**
* Discover Abilities in path.
*/
protected function discoverAbilities(): Collection
{
return DiscoverAbilities::within(
abilitiesPath: $this->abilitiesPath,
basePath: $this->basePath
);
}
}
Loading

0 comments on commit c119629

Please sign in to comment.