Installation
composer require chitanka/permission-bundle
Add to config/app.php under providers:
Chitanka\PermissionBundle\PermissionServiceProvider::class,
Publish the config:
php artisan vendor:publish --provider="Chitanka\PermissionBundle\PermissionServiceProvider" --tag="config"
First Use Case: Assigning a Permission
use Chitanka\PermissionBundle\Facades\Permission;
// Assign a permission to a user (e.g., 'edit_post')
Permission::assign('edit_post', 1); // User ID 1
// Check if a user has a permission
if (Permission::has('edit_post', 1)) {
// Grant access
}
Key Files to Review
config/permission.php (default permissions, roles, and mappings)app/Providers/ChitankaPermissionServiceProvider.php (customization entry point)routes/permission.php (if published; basic API routes)Role-Based Permissions
Define roles in config/permission.php:
'roles' => [
'admin' => ['create_post', 'edit_post', 'delete_post'],
'editor' => ['create_post', 'edit_post'],
],
Assign a role to a user:
Permission::assignRole('admin', 1);
Middleware Integration
Use the permission middleware in app/Http/Kernel.php:
protected $routeMiddleware = [
'permission' => \Chitanka\PermissionBundle\Middleware\PermissionMiddleware::class,
];
Apply to routes:
Route::get('/admin/posts', function () {
// ...
})->middleware('permission:edit_post');
Dynamic Permission Checks
// Check for multiple permissions
if (Permission::hasAny(['edit_post', 'delete_post'], 1)) {
// ...
}
// Check role membership
if (Permission::hasRole('admin', 1)) {
// ...
}
API Resource Protection
Use the Permission facade in controllers:
public function update(Request $request, Post $post) {
if (!Permission::has('edit_post', auth()->id())) {
abort(403);
}
// ...
}
DatabaseSeeder to preload permissions:
Permission::seedPermissions([
'create_post' => ['admin', 'editor'],
'delete_post' => ['admin'],
]);
Permission model by binding a new one in the service provider:
$this->app->bind('permission.model', function () {
return new \App\Models\CustomPermission();
});
PermissionAssigned):
Permission::addListener('PermissionAssigned', function ($permission, $userId) {
// Log or notify
});
Config Overrides
php artisan migrate
after publishing the config (check database/migrations/ for create_permissions_table.php).Caching Quirks
php artisan cache:clear
php artisan config:clear
config/permission.php for development:
'cache' => env('APP_ENV') !== 'local',
Middleware Conflicts
permission middleware does not auto-resolve the user. Ensure your middleware resolves the user ID (e.g., via auth()->id() or a request parameter):
public function handle($request, Closure $next, $permission) {
$userId = auth()->id(); // or $request->user()->id;
if (!Permission::has($permission, $userId)) {
abort(403);
}
return $next($request);
}
Permission Naming Collisions
roles, users) as custom permissions. The bundle uses these internally.Log Permission Checks:
Enable debug mode in config/permission.php:
'debug' => true,
This logs permission checks to storage/logs/permission.log.
Dump User Permissions:
dd(Permission::getUserPermissions(1)); // Returns array of permissions for user ID 1
Check Role Assignments:
dd(Permission::getUserRoles(1)); // Returns array of roles for user ID 1
Custom Storage Override the permission storage engine by binding a new implementation:
$this->app->bind('permission.storage', function () {
return new \App\Services\CustomPermissionStorage();
});
Implement the Chitanka\PermissionBundle\Contracts\PermissionStorage interface.
Permission Providers Extend permission logic by creating a custom provider:
use Chitanka\PermissionBundle\Contracts\PermissionProvider;
class CustomPermissionProvider implements PermissionProvider {
public function getPermissions() {
return ['custom_permission'];
}
}
Register it in the service provider:
$this->app->bind('permission.provider', function () {
return new CustomPermissionProvider();
});
API Extensions
Extend the default API routes by publishing and modifying routes/permission.php:
php artisan vendor:publish --provider="Chitanka\PermissionBundle\PermissionServiceProvider" --tag="routes"
How can I help you explore Laravel packages today?