Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Base image is from Microsoft
FROM mcr.microsoft.com/vscode/devcontainers/base:ubuntu-22.04

# Avoid interactive prompts (e.g. tzdata) during installation
ENV DEBIAN_FRONTEND=noninteractive

RUN mkdir -p /var/www/html

# Install 8.3 from Ondrej’s PPA
RUN apt-get update && apt-get install -y \
software-properties-common \
&& add-apt-repository ppa:ondrej/php -y \
&& apt-get update && apt-get install -y sqlite3 \
&& apt-get install -y php8.3-cli php8.3-dev \
php8.3-pgsql php8.3-sqlite3 php8.3-gd \
php8.3-curl \
php8.3-imap php8.3-mysql php8.3-mbstring \
php8.3-xml php8.3-zip php8.3-bcmath php8.3-soap \
php8.3-intl php8.3-readline \
php8.3-ldap \
php8.3-msgpack php8.3-igbinary php8.3-redis php8.3-swoole \
php8.3-memcached php8.3-pcov php8.3-imagick php8.3-xdebug \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
46 changes: 46 additions & 0 deletions .devcontainer/devcontainer.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
alias art='php artisan --ansi'
alias tinker='art tinker'
alias format='php vendor/bin/pint'
alias analyze='php vendor/bin/phpstan analyse'
alias test='php vendor/bin/paratest --coverage-html coverage'
alias stf='php vendor/bin/phpunit --filter'

# commit AI
function commit() {
commitMessage="$*"

git add .

if [ "$commitMessage" = "" ]; then
aicommits
return
fi

eval "git commit -a -m '${commitMessage}'"
}

# function gfind
function gfind() {
local excludeVendor="--exclude-dir=vendor" # Default to excluding the vendor directory
local searchString=""
local searchPath="./"

# Process all arguments
for arg in "$@"; do
if [[ "$arg" == "-w" || "$arg" == "--with-vendor" ]]; then
excludeVendor="" # Remove the exclude directive to include vendor
elif [[ -z "$searchString" && "$arg" != -* ]]; then
searchString="$arg" # Set the search string if it's not a flag and is the first non-flag argument
fi
done

# Check if a search string was provided
if [[ -z "$searchString" ]]; then
echo -e "${RED}Error: Missing required search string.${NC}"
echo -e "${YELLOW}Usage: ${NC}gfind searchString [-w|--with-vendor]"
return 1
fi

# Execute grep command
grep --include=\*.php $excludeVendor -rnw $searchPath -e "$searchString"
}
27 changes: 27 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{
"name": "Laravel RBAC",
"build": {
"dockerfile": "Dockerfile",
"context": "."
},
"features": {},
"customizations": {
"vscode": {
"extensions": [
"bmewburn.vscode-intelephense-client",
"calebporzio.better-phpunit",
"laravel.vscode-laravel",
"mikestead.dotenv",
"ms-azuretools.vscode-docker",
"php.intelephense"
],
"settings": {
"intelephense.environment.phpVersion": "8.3"
}
}
},
"remoteUser": "vscode",
"postCreateCommand": "",
"forwardPorts": [],
"portsAttributes": {}
}
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
.cursor
.idea
.php-cs-fixer.cache
.phpunit.cache
build
composer.lock
coverage
docs
vendor
workbench
node_modules
phpunit.xml
phpstan.neon
repomix-output.*
testbench.yaml
vendor
node_modules
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
[![run-tests](https://img.shields.io/github/actions/workflow/status/binary-cats/laravel-rbac/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/binary-cats/laravel-rbac/actions/workflows/run-tests.yml)
[![GitHub Code Style Action Status](https://github.styleci.io/repos/773171043/shield?branch=main)](https://github.com/binary-cats/laravel-rbac/actions?query=workflow%3A"Fix+PHP+code+style+issues"+branch%3Amain)

Enhance Laravel 11 with opinionated extension for [spatie/laravel-permissions](https://spatie.be/docs/laravel-permission/v6/introduction).
Enhance your Laravel 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
Expand Down
30 changes: 24 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
"php": "^8.2",
"illuminate/contracts": "^11.0|^12.0",
"lorisleiva/laravel-actions": "^2.8",
"spatie/laravel-collection-macros": "^7.0|^8.0",
"spatie/laravel-package-tools": "^1.16",
"spatie/laravel-permission": "^6.4"
},
Expand All @@ -36,15 +35,34 @@
},
"autoload-dev": {
"psr-4": {
"BinaryCats\\LaravelRbac\\Tests\\": "tests/"
"BinaryCats\\LaravelRbac\\Tests\\": "tests/",
"Workbench\\App\\": "workbench/app/",
"Workbench\\Database\\Factories\\": "workbench/database/factories/",
"Workbench\\Database\\Seeders\\": "workbench/database/seeders/"
}
},
"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"
"test": "vendor/bin/phpunit",
"post-autoload-dump": [
"@clear",
"@prepare"
],
"clear": "@php vendor/bin/testbench package:purge-skeleton --ansi",
"prepare": "@php vendor/bin/testbench package:discover --ansi",
"build": "@php vendor/bin/testbench workbench:build --ansi",
"serve": [
"Composer\\Config::disableProcessTimeout",
"@build",
"@php vendor/bin/testbench serve"
],
"lint": [
"@php vendor/bin/pint",
"@php vendor/bin/phpstan analyse"
]
},
"config": {
"sort-packages": true
Expand All @@ -57,11 +75,11 @@
"aliases": {
"Rbac": "BinaryCats\\LaravelRbac\\Facades\\Rbac"
}
},
},
"branch-alias": {
"dev-master": "1.x-dev"
}
}
},
"minimum-stability": "dev",
"prefer-stable": true
}
}
23 changes: 13 additions & 10 deletions src/Actions/StorePermission.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,25 @@
namespace BinaryCats\LaravelRbac\Actions;

use BackedEnum;
use Illuminate\Support\Facades\Artisan;
use Lorisleiva\Actions\Action;
use Spatie\Permission\Contracts\Permission;

class StorePermission extends Action
{
public function __construct(
protected readonly Permission $permission
) {
}

/**
* @param \BackedEnum $permission
* @param string $guard
*
* @return void
* Handle storing a permission.
*/
public function handle(BackedEnum $permission, string $guard): void
public function handle(BackedEnum|string $permission, string $guard): void
{
Artisan::call('permission:create-permission', [
'name' => $permission->value,
'guard' => $guard,
]);
if ($permission instanceof BackedEnum) {
$permission = $permission->value;
}

$this->permission::findOrCreate($permission, $guard);
}
}
18 changes: 10 additions & 8 deletions src/Actions/SyncDefinedRole.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@
namespace BinaryCats\LaravelRbac\Actions;

use BackedEnum;
use Illuminate\Support\Facades\Artisan;
use Lorisleiva\Actions\Action;
use Spatie\Permission\Contracts\Role;

class SyncDefinedRole extends Action
{
public function __construct(
protected readonly Role $role
) {
}

/**
* @return void
* Handle syncing a defined role.
*/
public function handle(string $name, string $guard, array $permissions): void
{
$permissions = collect($permissions)
->map(fn ($permission) => match (true) {
$permission instanceof BackedEnum => $permission->value,
default => (string) $permission
})->implode('|');
});

Artisan::call('permission:create-role', [
'name' => $name,
'guard' => $guard,
'permissions' => $permissions,
]);
$this->role::findOrCreate($name, $guard)
->syncPermissions($permissions);
}
}
36 changes: 18 additions & 18 deletions src/Commands/RbacResetCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,45 +24,45 @@ class RbacResetCommand extends Command

/**
* Execute the console command.
*
* @return int
*/
public function handle()
public function handle(): int
{
if ($this->databaseReady()) {
$this->withProgressBar($this->jobs(), fn ($job) => $job->dispatch());
$this->newLine();
$this->info('RBAC Reset Complete');
} else {
$this->error('DB is not ready');
if (!$this->databaseReady()) {
$this->error('DB is not ready. Please run migrations.');

return self::INVALID;
}

$this->jobs()->each(function (string $job) {
$this->components->task(
$job,
fn () => $this->laravel->make($job)->dispatchSync()
);
});

return self::SUCCESS;
}

/**
* Create the jobs.
*
* @return \Illuminate\Support\Collection
*/
protected function jobs(): Collection
{
$value = config('rbac.jobs');

return collect($value)
->map(fn ($job) => app()->make($job));
return collect($value);
}

/**
* True if the Database is prepared.
*
* @return bool
*/
protected function databaseReady(): bool
{
$value = config('permission.table_names');
$tables = config('permission.table_names', []);

return collect($value)
->validate(fn ($table) => Schema::hasTable($table));
return collect($tables)
->map(fn (string $table) => Schema::hasTable($table))
->reject()
->isEmpty();
}
}
2 changes: 1 addition & 1 deletion src/Jobs/ResetPermissions.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class ResetPermissions
/**
* @param string|null $guard
*/
public function __construct(string $guard = null)
public function __construct(?string $guard = null)
{
$this->guard = $guard ?? config('auth.defaults.guard');
}
Expand Down
16 changes: 5 additions & 11 deletions tests/Actions/StorePermissionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,18 @@
use BinaryCats\LaravelRbac\Actions\StorePermission;
use BinaryCats\LaravelRbac\Tests\Fixtures\Abilities\FooAbility;
use BinaryCats\LaravelRbac\Tests\TestCase;
use Illuminate\Support\Facades\Artisan;
use PHPUnit\Framework\Attributes\Test;

class StorePermissionTest extends TestCase
{
#[Test]
public function it_will_handle_creating_permission(): void
{
Artisan::expects('call')
->once()
->with(
'permission:create-permission',
[
'name' => 'una',
'guard' => 'web',
]
);

StorePermission::run(FooAbility::One, 'web');

$this->assertDatabaseHas(config('permission.table_names.permissions'), [
'name' => 'una',
'guard_name' => 'web',
]);
}
}
Loading
Loading