152 lines
4.6 KiB
Markdown
152 lines
4.6 KiB
Markdown
# c77_rbac Usage Guide - Part 3: Framework Integration
|
|
|
|
This is Part 3 of the comprehensive c77_rbac usage guide, covering detailed integration with popular web frameworks.
|
|
|
|
**Complete Guide Structure:**
|
|
- Part 1: Core Concepts and Basic Usage
|
|
- Part 2: Advanced Usage Scenarios
|
|
- **Part 3: Framework Integration** (this document)
|
|
- Part 4: Real-World Examples and Performance Optimization
|
|
- Part 5: Security Best Practices and Troubleshooting
|
|
|
|
## Table of Contents
|
|
|
|
1. [Laravel Integration](#laravel-integration)
|
|
2. [Django Integration](#django-integration)
|
|
3. [Ruby on Rails Integration](#ruby-on-rails-integration)
|
|
4. [Node.js Integration](#nodejs-integration)
|
|
|
|
## Laravel Integration
|
|
|
|
### Complete Laravel Setup
|
|
|
|
#### 1. Service Provider
|
|
|
|
```php
|
|
<?php
|
|
// app/Providers/RbacServiceProvider.php
|
|
|
|
namespace App\Providers;
|
|
|
|
use Illuminate\Support\ServiceProvider;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Gate;
|
|
use App\Services\RbacService;
|
|
|
|
class RbacServiceProvider extends ServiceProvider
|
|
{
|
|
public function register()
|
|
{
|
|
$this->app->singleton(RbacService::class);
|
|
}
|
|
|
|
public function boot()
|
|
{
|
|
// Register middleware
|
|
$this->app['router']->aliasMiddleware('rbac.context',
|
|
\App\Http\Middleware\SetRbacContext::class);
|
|
$this->app['router']->aliasMiddleware('rbac.require',
|
|
\App\Http\Middleware\RequirePermission::class);
|
|
|
|
// Integrate with Laravel Gates
|
|
Gate::before(function ($user, $ability) {
|
|
// Check RBAC format: 'feature:scope_type/scope_id'
|
|
if (strpos($ability, ':') !== false) {
|
|
[$feature, $scope] = explode(':', $ability, 2);
|
|
if (strpos($scope, '/') !== false) {
|
|
[$scopeType, $scopeId] = explode('/', $scope, 2);
|
|
return app(RbacService::class)->can($feature, $scopeType, $scopeId);
|
|
}
|
|
}
|
|
|
|
// Default to global scope
|
|
return app(RbacService::class)->can($ability, 'global', 'all');
|
|
});
|
|
|
|
// Register Artisan commands
|
|
if ($this->app->runningInConsole()) {
|
|
$this->commands([
|
|
\App\Console\Commands\RbacAssignRole::class,
|
|
\App\Console\Commands\RbacSyncAdmin::class,
|
|
\App\Console\Commands\RbacListPermissions::class,
|
|
]);
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
#### 2. RBAC Service
|
|
|
|
```php
|
|
<?php
|
|
// app/Services/RbacService.php
|
|
|
|
namespace App\Services;
|
|
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Auth;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class RbacService
|
|
{
|
|
/**
|
|
* Check if current user has access to a feature
|
|
*/
|
|
public function can(string $feature, string $scopeType = 'global', string $scopeId = 'all'): bool
|
|
{
|
|
if (!Auth::check()) {
|
|
return false;
|
|
}
|
|
|
|
$userId = Auth::id();
|
|
$cacheKey = "rbac:can:{$userId}:{$feature}:{$scopeType}:{$scopeId}";
|
|
|
|
return Cache::remember($cacheKey, 300, function () use ($feature, $userId, $scopeType, $scopeId) {
|
|
try {
|
|
$result = DB::selectOne(
|
|
'SELECT public.c77_rbac_can_access(?, ?, ?, ?) AS allowed',
|
|
[$feature, (string)$userId, $scopeType, $scopeId]
|
|
);
|
|
|
|
return $result->allowed ?? false;
|
|
} catch (\Exception $e) {
|
|
Log::error('RBAC permission check failed', [
|
|
'feature' => $feature,
|
|
'user_id' => $userId,
|
|
'scope_type' => $scopeType,
|
|
'scope_id' => $scopeId,
|
|
'error' => $e->getMessage()
|
|
]);
|
|
return false;
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Assign role to user
|
|
*/
|
|
public function assignRole(int $userId, string $role, string $scopeType = 'global', string $scopeId = 'all'): bool
|
|
{
|
|
try {
|
|
DB::statement(
|
|
'SELECT public.c77_rbac_assign_subject(?, ?, ?, ?)',
|
|
[(string)$userId, $role, $scopeType, $scopeId]
|
|
);
|
|
|
|
// Clear user's permission cache
|
|
$this->clearUserCache($userId);
|
|
|
|
Log::info('Role assigned', [
|
|
'user_id' => $userId,
|
|
'role' => $role,
|
|
'scope_type' => $scopeType,
|
|
'scope_id' => $scopeId
|
|
]);
|
|
|
|
return true;
|
|
} catch (\Exception $e) {
|
|
Log::error('Failed to assign role', [
|
|
'user_id' => $userId,
|
|
'role' => $role,
|
|
|