anwar / dynamic-roles
Complete dynamic role and permission management package with caching and API support
Requires
- php: ^8.0
- illuminate/cache: ^9.0|^10.0|^11.0
- illuminate/database: ^9.0|^10.0|^11.0
- illuminate/http: ^9.0|^10.0|^11.0
- illuminate/support: ^9.0|^10.0|^11.0
- spatie/laravel-permission: ^5.0|^6.0
Requires (Dev)
- orchestra/testbench: ^7.0|^8.0|^9.0
- phpunit/phpunit: ^9.0|^10.0
This package is auto-updated.
Last update: 2025-09-11 05:06:12 UTC
README
A comprehensive Laravel package for dynamic role and permission management with caching, API support, and complete database-driven URL management. Perfect for applications with complex permission requirements that need to be managed without touching code.
Features
- 🚀 Dynamic Permission Management: Create and manage permissions without touching code
- 🎯 URL-Based Access Control: Control access to specific URLs and HTTP methods
- ⚡ High Performance Caching: Configurable caching with Redis, Memcached, or other drivers
- 🔧 Auto-Discovery: Automatically discover and register routes from your application
- 🌐 Complete API: Full REST API for frontend integration (perfect for Next.js)
- 🛡️ Middleware Protection: Ready-to-use middleware for route protection
- 📊 Analytics & Logging: Track permission checks and access patterns
- 🎨 Flexible Configuration: Highly configurable to fit any application structure
- 💾 Import/Export: Backup and restore permission configurations
- 🔄 Bulk Operations: Efficiently manage permissions for multiple entities
- 🍔 Menu Management: Create hierarchical menu systems with role/permission-based access
- 🧭 Breadcrumb Support: Automatic breadcrumb generation for nested menus
- 🏗️ Tree Structure: Build complex nested menu structures with unlimited depth
Installation
1. Install the Package
Run on terminal:
composer require anwar/dynamic-roles
Or add it on your main composer.json
Then run:
composer install
2. Install Spatie Laravel Permission (Required Dependency)
composer require spatie/laravel-permission
php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider"
php artisan migrate
3. Publish and Run Migrations
# Publish configuration php artisan vendor:publish --tag=dynamic-roles-config # Publish migrations php artisan vendor:publish --tag=dynamic-roles-migrations # Run migrations php artisan migrate
4. Add Service Provider (If not auto-discovered)
Add to config/app.php
:
'providers' => [ // ... Anwar\DynamicRoles\DynamicRolesServiceProvider::class, ],
5. Add Traits to User Model
<?php namespace App\Models; use Illuminate\Foundation\Auth\User as Authenticatable; use Spatie\Permission\Traits\HasRoles; class User extends Authenticatable { use HasRoles; // ... your existing code }
Configuration
Environment Variables
Add these to your .env
file:
# Cache Configuration DYNAMIC_ROLES_CACHE_ENABLED=true DYNAMIC_ROLES_CACHE_DRIVER=redis DYNAMIC_ROLES_CACHE_PREFIX=dynamic_roles DYNAMIC_ROLES_CACHE_TTL=3600 # API Configuration DYNAMIC_ROLES_ENABLE_API=true DYNAMIC_ROLES_API_PREFIX=api/dynamic-roles # Auto-Discovery DYNAMIC_ROLES_AUTO_DISCOVERY=true DYNAMIC_ROLES_AUTO_REGISTER_URLS=true # Security DYNAMIC_ROLES_SUPER_ADMIN=super-admin DYNAMIC_ROLES_BYPASS_PERMISSIONS=false DYNAMIC_ROLES_LOG_CHECKS=false
Configuration File
The package publishes a configuration file at config/dynamic-roles.php
. Key sections include:
- Cache Settings: Configure caching behavior and drivers
- Database Settings: Customize table names and connections
- API Settings: Configure API routes and middleware
- Security Settings: Set super admin roles and security options
- Discovery Settings: Configure auto-discovery patterns
Usage
Basic Usage
1. Register URLs with Permissions
use \DynamicRoles\Facades\DynamicRoles; // Register a URL with specific permissions DynamicRoles::registerUrl( '/api/users', 'GET', ['users.view', 'users.list'], [ 'name' => 'users.index', 'description' => 'List all users', 'category' => 'api' ] ); // Auto-discover all routes DynamicRoles::autoDiscoverRoutes();
2. Use Middleware
// In your routes/api.php Route::middleware(['dynamic.permission'])->group(function () { Route::get('/users', [UserController::class, 'index']); Route::post('/users', [UserController::class, 'store']); }); // With specific permissions Route::get('/admin/users', [UserController::class, 'adminIndex']) ->middleware('dynamic.permission:admin.users.view'); // With role-based access Route::middleware(['dynamic.role:admin,manager'])->group(function () { Route::get('/admin/dashboard', [AdminController::class, 'dashboard']); });
3. Programmatic Permission Checks
use \DynamicRoles\Services\UrlPermissionService; $urlPermissionService = app(UrlPermissionService::class); // Check if user has permission for a specific URL $hasPermission = $urlPermissionService->checkUrlPermission( $user, '/api/users', 'GET' ); if ($hasPermission) { // Allow access } else { // Deny access }
API Usage
The package provides a complete REST API for managing roles and permissions:
Authentication
All API endpoints require authentication. Configure the middleware in the config file:
'api' => [ 'middleware' => [ 'api', 'auth:sanctum', // or 'auth:api', 'jwt.auth', etc. ], ],
API Endpoints
URL Management:
# Get all URLs GET /api/dynamic-roles/urls # Create new URL POST /api/dynamic-roles/urls { "url": "/api/products", "method": "GET", "permissions": ["products.view"], "roles": ["user", "admin"] } # Update URL PUT /api/dynamic-roles/urls/{id} # Delete URL DELETE /api/dynamic-roles/urls/{id} # Check permission POST /api/dynamic-roles/urls/check-permission { "url": "/api/products", "method": "GET" } # Auto-discover routes POST /api/dynamic-roles/urls/auto-discover
Role Management:
# Get all roles GET /api/dynamic-roles/roles # Create role POST /api/dynamic-roles/roles { "name": "editor", "permissions": ["posts.create", "posts.edit"] } # Assign permissions to role POST /api/dynamic-roles/roles/{roleId}/permissions { "permissions": ["posts.create", "posts.edit", "posts.delete"] } # Get role permissions GET /api/dynamic-roles/roles/{roleId}/permissions
User Management:
# Assign role to user POST /api/dynamic-roles/users/assign-role { "user_id": 1, "role": "editor" } # Get user permissions GET /api/dynamic-roles/users/{userId}/permissions
Frontend Integration (Next.js Example)
// lib/permissions.ts interface PermissionCheck { url: string; method: string; } export async function checkPermission({ url, method }: PermissionCheck): Promise<boolean> { try { const response = await fetch('/api/dynamic-roles/urls/check-permission', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${getAuthToken()}`, }, body: JSON.stringify({ url, method }), }); const result = await response.json(); return result.data.has_permission; } catch (error) { console.error('Permission check failed:', error); return false; } } // Usage in React component import { checkPermission } from '@/lib/permissions'; export default function ProductList() { const [canEdit, setCanEdit] = useState(false); useEffect(() => { checkPermission({ url: '/api/products', method: 'PUT' }) .then(setCanEdit); }, []); return ( <div> {canEdit && <button>Edit Product</button>} </div> ); }
Advanced Features
1. Custom Permission Patterns
Configure auto-discovery patterns in config/dynamic-roles.php
:
'discovery' => [ 'permission_patterns' => [ 'create' => ['store', 'create', 'add'], 'read' => ['index', 'show', 'view', 'list'], 'update' => ['update', 'edit', 'modify'], 'delete' => ['destroy', 'delete', 'remove'], 'admin' => ['admin', 'manage'], ], ],
2. Cache Configuration
'cache' => [ 'enabled' => true, 'driver' => 'redis', // redis, memcached, file, etc. 'ttl' => 3600, 'tags' => [ 'permissions' => 'dynamic_roles_permissions', 'roles' => 'dynamic_roles_roles', 'urls' => 'dynamic_roles_urls', ], ],
3. Bulk Operations
use \DynamicRoles\Services\RolePermissionService; $rolePermissionService = app(RolePermissionService::class); // Bulk assign permissions to roles $rolePermissionService->bulkAssignPermissions([ 'admin' => ['users.create', 'users.edit', 'users.delete'], 'editor' => ['posts.create', 'posts.edit'], 'viewer' => ['posts.view'], ]); // Bulk assign roles to users $rolePermissionService->bulkAssignRoles([ 1 => ['admin'], 2 => ['editor'], 3 => ['viewer'], ]);
4. Import/Export Configuration
// Export current configuration $config = $rolePermissionService->exportConfiguration(); file_put_contents('permissions-backup.json', json_encode($config, JSON_PRETTY_PRINT)); // Import configuration $config = json_decode(file_get_contents('permissions-backup.json'), true); $rolePermissionService->importConfiguration($config);
Artisan Commands
The package provides several useful Artisan commands:
# Sync permissions and auto-discover routes php artisan dynamic-roles:sync-permissions --auto-discover --clear-cache # Clear specific caches php artisan dynamic-roles:clear-cache --user=1 php artisan dynamic-roles:clear-cache --role=2 php artisan dynamic-roles:clear-cache --url=/api/users --method=GET # Clear all permission cache php artisan dynamic-roles:clear-cache # Publish configuration (force overwrite) php artisan dynamic-roles:publish-config
Testing
Create tests for your permissions:
<?php namespace Tests\Feature; use Tests\TestCase; use Illuminate\Foundation\Testing\RefreshDatabase; use Anwar\DynamicRoles\Facades\DynamicRoles; class PermissionTest extends TestCase { use RefreshDatabase; public function test_user_can_access_allowed_url() { $user = User::factory()->create(); $user->assignRole('user'); DynamicRoles::registerUrl('/api/profile', 'GET', ['profile.view']); $response = $this->actingAs($user) ->getJson('/api/profile'); $response->assertStatus(200); } public function test_user_cannot_access_forbidden_url() { $user = User::factory()->create(); DynamicRoles::registerUrl('/api/admin', 'GET', ['admin.access']); $response = $this->actingAs($user) ->getJson('/api/admin'); $response->assertStatus(403); } }
Performance Optimization
1. Caching Strategy
The package uses intelligent caching:
- User permissions are cached per user
- URL permissions are cached per URL+method combination
- Role permissions are cached per role
- Cache invalidation happens automatically on changes
2. Database Optimization
- Proper indexing on all lookup columns
- Eager loading of relationships
- Optimized queries for permission checks
3. Configuration Tips
// Enable preloading for better performance 'performance' => [ 'preload_permissions' => true, 'eager_load_relationships' => true, 'batch_permission_checks' => true, ],
Security Considerations
1. Super Admin Role
Configure a super admin role that bypasses all permission checks:
'security' => [ 'super_admin_role' => 'super-admin', 'bypass_permissions' => false, // Never set to true in production ],
2. API Security
- Always use authentication middleware
- Consider rate limiting for API endpoints
- Validate all input data
- Log permission checks for auditing
3. Database Security
- Use database transactions for bulk operations
- Implement soft deletes for audit trails
- Regular backups of permission configurations
Troubleshooting
Common Issues
-
Middleware not working
- Ensure middleware is registered in kernel
- Check route definitions
- Verify user authentication
-
Cache not clearing
- Check cache driver configuration
- Ensure proper Redis/Memcached connection
- Verify cache key patterns
-
Auto-discovery not working
- Check route registration timing
- Verify excluded patterns
- Ensure proper controller naming
Debug Mode
Enable detailed logging:
DYNAMIC_ROLES_LOG_CHECKS=true
Check logs at storage/logs/laravel.log
for detailed permission check information.
Contributing
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
License
This package is open-sourced software licensed under the MIT license.
Support
For support, please check:
- This documentation
- Laravel logs (
storage/logs/laravel.log
) - Package configuration (
config/dynamic-roles.php
) - Database tables and relationships
Changelog
Version 1.0.0
- Initial release
- Complete role and permission management
- API endpoints for frontend integration
- Caching system with multiple driver support
- Auto-discovery functionality
- Comprehensive middleware protection
- Import/export capabilities
- Artisan commands for management
- Complete documentation and examples
Menu Management
The package includes a complete menu management system that allows you to create hierarchical menu structures with role and permission-based access control.
Creating Menus
use Anwar\DynamicRoles\Services\MenuService; $menuService = app(MenuService::class); // Create a parent menu $parentMenu = $menuService->createMenu([ 'name' => 'dashboard', 'label' => 'Dashboard', 'url' => '/dashboard', 'icon' => 'fas fa-tachometer-alt', 'is_active' => true, 'is_visible' => true, 'sort_order' => 1, ]); // Create a child menu $childMenu = $menuService->createMenu([ 'name' => 'user_management', 'label' => 'User Management', 'url' => '/users', 'icon' => 'fas fa-users', 'parent_id' => $parentMenu->id, 'sort_order' => 1, 'permissions' => [1, 2], // Permission IDs 'roles' => [1], // Role IDs ]);
Getting Menu Tree
// Get menu tree for current user (filtered by permissions) $userMenuTree = $menuService->getMenuTreeForUser(auth()->user()); // Get full menu tree (admin view) $fullMenuTree = $menuService->getFullMenuTree();
Menu API Endpoints
All menu endpoints are available under /api/dynamic-roles/menus/
:
GET /menus
- List all menus with filteringGET /menus/tree
- Get menu tree for current userPOST /menus
- Create a new menuGET /menus/{id}
- Get specific menuPUT /menus/{id}
- Update menuDELETE /menus/{id}
- Delete menuGET /menus/{id}/breadcrumbs
- Get breadcrumbs for menuPOST /menus/reorder
- Reorder menu itemsPOST /menus/{id}/assign-permissions
- Assign permissions to menuPOST /menus/{id}/assign-roles
- Assign roles to menu
Menu Configuration
Configure menu behavior in config/dynamic-roles.php
:
'menu' => [ 'enabled' => true, 'cache_enabled' => true, 'cache_ttl' => 1800, // 30 minutes 'max_depth' => 5, 'auto_permissions' => true, // Auto create permissions for menu items 'icons' => [ 'supported_libraries' => ['fontawesome', 'feather', 'heroicons', 'material'], 'default_library' => 'fontawesome', ], ],