# Sistema de Middleware e Guard - OfficeGest

Esta documentação abrange o sistema de middleware e o sistema Guard (autenticação) do OfficeGest, fornecendo um guia completo desde o básico até implementações avançadas para desenvolvedores de todos os níveis.

## 📋 Índice

1. [Visão Geral](#-visão-geral)
2. [Sistema de Middleware](#-sistema-de-middleware)
3. [Sistema Guard](#-sistema-guard)
4. [Middlewares Específicos](#-middlewares-específicos)
5. [Exemplos Práticos para ERP](#-exemplos-práticos-para-erp)
6. [Implementações Futuras](#-implementações-futuras)
7. [Troubleshooting](#-troubleshooting)

## 🔍 Visão Geral

O OfficeGest implementa um sistema robusto de middleware baseado no padrão Pipeline, similar ao Laravel, permitindo o processamento sequencial de requisições HTTP através de uma cadeia de middlewares configuráveis.

### Arquitetura Principal

```
Request → MiddlewareManager → Pipeline → Controller → Response
    ↓
[Auth] → [Throttle] → [Module] → [Guard] → [JSON] → Destino
```

## 🛠️ Sistema de Middleware

### Conceitos Fundamentais

#### MiddlewareInterface
Todos os middlewares devem implementar a interface `MiddlewareInterface`:

```php
namespace Og\Modules\Common\Middleware;

interface MiddlewareInterface
{
    public function handle(Request $request, Closure $next): mixed;
}
```

#### MiddlewareManager
Gerencia middlewares globais, grupos e aliases:

```php
// Registro de middleware global
$middlewareManager->registerGlobalMiddleware('auth');

// Registro de grupo
$middlewareManager->registerMiddlewareGroup('api', [
    'throttle',
    'json_response'
]);

// Registro de alias
$middlewareManager->registerMiddlewareAlias('auth', AuthMiddleware::class);
```

### Configuração de Middlewares

O arquivo `Modules/Common/Config/middleware.php` define:

```php
return [
    'global' => [
        // Middlewares executados em todas as rotas
    ],
    
    'groups' => [
        'api' => ['throttle', 'json_response'],
        'auth' => ['auth'],
        'guard.api' => ['guard.auth', 'guard.throttle:api', 'json_response'],
    ],
    
    'aliases' => [
        'auth' => AuthMiddleware::class,
        'og-module' => OgModuleMiddleware::class,
        'guard.auth' => GuardAuthMiddleware::class,
    ]
];
```

### Pipeline de Processamento

O sistema utiliza o padrão Pipeline com `array_reduce` para criar a cadeia:

```php
$pipeline = array_reduce(
    array_reverse($middlewareStack),
    function ($carry, $middleware) {
        return function ($request) use ($carry, $middleware) {
            [$name, $params] = $this->parseMiddleware($middleware);
            $instance = $this->resolveMiddleware($name);
            return $instance->handle($request, $carry, $params);
        };
    },
    $destination
);
```

## 🛡️ Sistema Guard

O Guard é um sistema de autenticação baseado em tokens, similar ao Laravel Sanctum, oferecendo:

### Características Principais

- **Personal Access Tokens**: Tokens de longa duração para APIs
- **SPA Tokens**: Tokens de curta duração para Single Page Applications  
- **Rate Limiting**: Controle de taxa integrado
- **Abilities/Permissions**: Sistema de permissões granulares
- **Segurança**: Hash de tokens, expiração automática, limpeza de tokens

### GuardManager

Principal classe para gestão de autenticação:

```php
// Autenticação
$user = $guard->authenticate();
$isAuthenticated = $guard->check();
$userId = $guard->id();

// Criação de tokens
$token = $guard->createToken($userId, 'api-token', ['api:read', 'api:write']);
$spaToken = $guard->createSpaToken($userId);

// Permissões
$canAdmin = $guard->tokenCan('admin');
$canAny = $guard->tokenCanAny(['admin', 'user']);

// Gestão
$guard->revokeCurrentToken();
$guard->revokeAllTokens();
$tokens = $guard->tokens();
```

### PersonalAccessToken

Representa um token de acesso:

```php
$token = new PersonalAccessToken([
    'id' => 1,
    'name' => 'api-token',
    'abilities' => ['api:read', 'api:write'],
    'expires_at' => '2024-12-31 23:59:59'
]);

// Verificações
$isValid = $token->isValid();
$hasAbility = $token->hasAbility('api:read');
$plainText = $token->getPlainTextToken(); // guard_1|abc123...
```

## 📦 Middlewares Específicos

### AuthMiddleware

Autenticação básica usando o sistema de usuários do OfficeGest:

```php
class AuthMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, Closure $next): mixed
    {
        $token = $request->header('Authorization') ?? $request->get('token');
        $isLogged = $this->user->IsLogged();
        
        if (!$token || !$isLogged) {
            return Response::json([
                'error' => 'Unauthorized',
                'message' => 'The token is missing'
            ], 401);
        }
        
        return $next($request);
    }
}
```

**Uso prático:**
```php
Route::get('/api/vendas', VendasController::class)->middleware('auth');
```

### OgModuleMiddleware

Verifica se o usuário tem acesso aos módulos específicos do ERP:

```php
class OgModuleMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, Closure $next, ?array $modules = null): mixed
    {
        $application = $request->officegestApplication();
        
        foreach ($modules as $module) {
            if (!$application->hasModule(strtoupper($module))) {
                return Response::json([
                    'error' => 'Unauthorized',
                    'message' => "The application doesn't have the module $module"
                ]);
            }
        }
        
        return $next($request);
    }
}
```

**Uso prático:**
```php
// Verificar módulo AMS (Airport Management System)
Route::group(['middleware' => 'og-module:ams'], function() {
    Route::get('/api/ams/flights', AmsFlightController::class);
    Route::get('/api/ams/handling', AmsHandlingController::class);
});

// Verificar múltiplos módulos
Route::get('/api/reports/integrated', function() {
    // Precisa de WMSO (Warehouse) e VENDAS (Sales)
})->middleware('og-module:wmso,vendas');
```

### ThrottleMiddleware

Rate limiting baseado em IP com headers padrão:

```php
class ThrottleMiddleware implements MiddlewareInterface
{
    private int $maxAttempts = 60; // Max requests per minute
    
    public function handle(Request $request, Closure $next): mixed
    {
        $key = $this->resolveRequestSignature($request);
        
        if ($this->tooManyAttempts($key, $this->maxAttempts)) {
            return Response::json([
                'error' => 'Too Many Requests',
                'retry_after' => $this->getRetryAfter($key)
            ], 429);
        }
        
        $response = $next($request);
        
        // Adiciona headers de rate limit
        $response->headers([
            'X-RateLimit-Limit' => $this->maxAttempts,
            'X-RateLimit-Remaining' => max(0, $this->maxAttempts - $this->attempts($key)),
            'X-RateLimit-Reset' => $this->getResetTime($key)
        ]);
        
        return $response;
    }
}
```

### JsonResponseMiddleware

Garante que todas as respostas sejam JSON válido:

```php
class JsonResponseMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, Closure $next): mixed
    {
        $response = $next($request);
        
        // Se não é um Response object, converte para JSON
        if (!$response instanceof Response) {
            if (is_array($response) || is_object($response)) {
                return Response::json($response);
            }
            return Response::json(['data' => $response]);
        }
        
        if (!$response->getHeader('Content-Type')) {
            $response->header('Content-Type', 'application/json');
        }
        
        return $response;
    }
}
```

### Guard Middlewares

#### GuardAuthMiddleware
```php
Route::get('/api/secure', function() {
    return Guard::user();
})->middleware('guard.auth');
```

#### GuardAbilitiesMiddleware
```php
Route::delete('/api/admin/users', function() {
    // Apenas tokens com permissões admin ou users:delete
})->middleware('guard.abilities:admin,users:delete');
```

#### GuardThrottleMiddleware
```php
Route::group(['middleware' => 'guard.throttle:api'], function() {
    // Rate limiting para APIs (60 req/min)
});

Route::group(['middleware' => 'guard.throttle:spa'], function() {
    // Rate limiting para SPAs (120 req/min)
});
```

## 💼 Exemplos Práticos para ERP

### 1. Sistema de Vendas com Autenticação Completa

```php
// Routes/Api.php - Módulo Vendas
Route::group([
    'prefix' => 'api/vendas',
    'middleware' => ['guard.api', 'og-module:vendas']
], function() {
    
    // Consultar vendas - apenas leitura
    Route::get('/consultar', [VendasController::class, 'index'])
          ->middleware('guard.abilities:vendas:read');
    
    // Criar venda - permissão de escrita
    Route::post('/criar', [VendasController::class, 'store'])
          ->middleware('guard.abilities:vendas:write');
    
    // Anular venda - permissão especial
    Route::delete('/{id}/anular', [VendasController::class, 'cancel'])
          ->middleware('guard.abilities:vendas:cancel,admin');
    
    // Relatórios - permissão de admin ou relatórios
    Route::get('/relatorios', [VendasController::class, 'reports'])
          ->middleware('guard.abilities:admin,reports:read');
});
```

### 2. Sistema de Stocks/Armazém (WMSO)

```php
Route::group([
    'prefix' => 'api/stocks',
    'middleware' => ['guard.api', 'og-module:wmso']
], function() {
    
    // Consulta de stocks - todos podem ver
    Route::get('/consultar', [StocksController::class, 'index']);
    
    // Movimentações de stock - apenas operadores
    Route::post('/movimentar', [StocksController::class, 'move'])
          ->middleware('guard.abilities:stocks:move,operator');
    
    // Inventário - apenas supervisores
    Route::post('/inventario', [StocksController::class, 'inventory'])
          ->middleware('guard.abilities:stocks:inventory,supervisor');
    
    // Rate limiting especial para operações críticas
    Route::group(['middleware' => 'guard.throttle:critical'], function() {
        Route::post('/transfer', [StocksController::class, 'transfer'])
              ->middleware('guard.abilities:stocks:transfer');
    });
});
```

### 3. Sistema Aeroportuário (AMS)

```php
Route::group([
    'prefix' => 'api/ams',
    'middleware' => ['guard.api', 'og-module:ams']
], function() {
    
    // Informações públicas de voos
    Route::get('/flights/public', [AmsFlightController::class, 'public']);
    
    // Gestão de handling - apenas pessoal autorizado
    Route::group(['middleware' => 'guard.abilities:ams:handling'], function() {
        Route::get('/handling', [AmsHandlingController::class, 'index']);
        Route::post('/handling', [AmsHandlingController::class, 'store']);
        Route::put('/handling/{id}', [AmsHandlingController::class, 'update']);
    });
    
    // Concierge - acesso especial
    Route::group([
        'prefix' => 'concierge',
        'middleware' => 'guard.abilities:ams:concierge,concierge'
    ], function() {
        Route::resource('services', AmsConciergeController::class);
        Route::post('/{id}/attachments', [AmsConciergeController::class, 'addAttachment']);
    });
    
    // Operações críticas com throttling especial
    Route::group(['middleware' => 'guard.throttle:ams_critical'], function() {
        Route::post('/emergency', [AmsEmergencyController::class, 'handle'])
              ->middleware('guard.abilities:ams:emergency,emergency');
    });
});
```

### 4. Sistema Multi-Módulo com Verificações Complexas

```php
// Controller para operações que precisam de múltiplos módulos
class IntegratedOperationsController extends BaseController
{
    public function crossModuleReport(Request $request)
    {
        // Esta operação precisa de VENDAS + WMSO + FINANCEIRO
        // Já verificado pelo middleware og-module:vendas,wmso,financeiro
        
        $user = Guard::user();
        
        // Verificações adicionais baseadas em permissões
        if (!Guard::tokenCan('reports:integrated')) {
            return Response::json([
                'error' => 'Insufficient permissions for integrated reports'
            ], 403);
        }
        
        // Lógica do relatório integrado
        return Response::json([
            'sales_data' => $this->getSalesData(),
            'stock_data' => $this->getStockData(),
            'financial_data' => $this->getFinancialData()
        ]);
    }
}

// Rota correspondente
Route::get('/api/reports/integrated', [IntegratedOperationsController::class, 'crossModuleReport'])
      ->middleware([
          'guard.api',
          'og-module:vendas,wmso,financeiro',
          'guard.abilities:reports:integrated,admin'
      ]);
```

### 5. Login SPA para ERP

```php
class AuthController extends BaseController
{
    public function login(Request $request)
    {
        $credentials = [
            'username' => $request->input('username'),
            'password' => $request->input('password')
        ];
        
        $token = Guard::loginForSpa($credentials);
        
        if (!$token) {
            return Response::json([
                'error' => 'Invalid credentials'
            ], 401);
        }
        
        // Definir cookie seguro para SPA
        setcookie(
            'guard_token',
            $token->getPlainTextToken(),
            [
                'expires' => time() + (24 * 60 * 60),
                'path' => '/',
                'secure' => true,
                'httponly' => true,
                'samesite' => 'Strict'
            ]
        );
        
        $user = Guard::user();
        
        return Response::json([
            'message' => 'Login successful',
            'user' => [
                'id' => $user['id'],
                'name' => $user['nome'],
                'modules' => $this->getUserModules($user['id'])
            ],
            'expires_at' => $token->getExpiresAt()
        ]);
    }
    
    private function getUserModules(int $userId): array
    {
        // Lógica para obter módulos do usuário
        $app = app('app');
        return $app->getUserModules($userId);
    }
}
```

### 6. Middleware Customizado para Contexto ERP

```php
class ErpContextMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, Closure $next): mixed
    {
        $user = Guard::user();
        
        if (!$user) {
            return $next($request);
        }
        
        // Adicionar informações de contexto ERP
        $context = [
            'user_id' => $user['id'],
            'company_id' => $user['empresa'] ?? null,
            'branch_id' => $user['filial'] ?? null,
            'fiscal_year' => $this->getCurrentFiscalYear(),
            'permissions' => $this->getUserPermissions($user['id'])
        ];
        
        // Adicionar ao request para uso posterior
        $request->attributes->set('erp_context', $context);
        
        return $next($request);
    }
    
    private function getCurrentFiscalYear(): int
    {
        return (int) date('Y');
    }
    
    private function getUserPermissions(int $userId): array
    {
        // Buscar permissões específicas do ERP
        return app('database')
            ->select('permissao')
            ->from('user_permissions')
            ->where('user_id', $userId)
            ->where('ativo', 1)
            ->get()
            ->pluck('permissao')
            ->toArray();
    }
}
```

### 7. Rate Limiting Avançado por Módulo

```php
class ModuleAwareThrottleMiddleware implements MiddlewareInterface
{
    private array $moduleRateLimits = [
        'vendas' => ['requests' => 100, 'minutes' => 1],
        'wmso' => ['requests' => 200, 'minutes' => 1],
        'ams' => ['requests' => 50, 'minutes' => 1],
        'financeiro' => ['requests' => 30, 'minutes' => 1]
    ];
    
    public function handle(Request $request, Closure $next): mixed
    {
        $module = $this->detectModule($request);
        $limits = $this->moduleRateLimits[$module] ?? ['requests' => 60, 'minutes' => 1];
        
        $key = "throttle:{$module}:" . ($this->getUserKey($request));
        $attempts = $this->getAttempts($key);
        
        if ($attempts >= $limits['requests']) {
            return Response::json([
                'error' => 'Rate limit exceeded for module ' . $module,
                'limit' => $limits['requests'],
                'retry_after' => $limits['minutes'] * 60
            ], 429);
        }
        
        $this->incrementAttempts($key, $limits['minutes']);
        return $next($request);
    }
    
    private function detectModule(Request $request): string
    {
        $path = $request->getPathInfo();
        
        if (str_contains($path, '/api/vendas/')) return 'vendas';
        if (str_contains($path, '/api/stocks/') || str_contains($path, '/api/wmso/')) return 'wmso';
        if (str_contains($path, '/api/ams/')) return 'ams';
        if (str_contains($path, '/api/financeiro/')) return 'financeiro';
        
        return 'general';
    }
}
```

## 🔮 Implementações Futuras

### ApplicationGuard

Sistema de autenticação baseado em aplicações/empresas:

```php
class ApplicationGuard implements GuardInterface
{
    private array $applications = [];
    
    public function authenticate(Request $request): ?ApplicationContext
    {
        $appToken = $request->header('X-Application-Token');
        $userToken = $request->header('Authorization');
        
        // Verificar token de aplicação primeiro
        $application = $this->validateApplicationToken($appToken);
        if (!$application) {
            return null;
        }
        
        // Verificar token de usuário no contexto da aplicação
        $user = $this->validateUserInApplication($userToken, $application);
        
        return new ApplicationContext([
            'application' => $application,
            'user' => $user,
            'modules' => $application->getActiveModules(),
            'permissions' => $user->getPermissionsInApplication($application->getId())
        ]);
    }
}
```

### Multi-Tenancy Guard

Suporte para múltiplas empresas/inquilinos:

```php
class MultiTenantGuard extends GuardManager
{
    public function authenticateForTenant(string $tenantId): ?array
    {
        $token = $this->extractTokenFromRequest();
        $tenant = $this->resolveTenant($tenantId);
        
        if (!$tenant || !$tenant->isActive()) {
            return null;
        }
        
        // Validar token no contexto do tenant
        $personalAccessToken = $this->tokenManager->findTokenForTenant($token, $tenantId);
        
        if (!$personalAccessToken || !$personalAccessToken->isValid()) {
            return null;
        }
        
        return $this->createTenantContext($personalAccessToken, $tenant);
    }
}
```

### Advanced Permission System

Sistema de permissões hierárquicas:

```php
class HierarchicalPermissionMiddleware implements MiddlewareInterface
{
    private array $permissionHierarchy = [
        'admin' => ['*'],
        'manager' => ['vendas:*', 'stocks:read', 'reports:read'],
        'operator' => ['vendas:read', 'stocks:move'],
        'viewer' => ['*.read']
    ];
    
    public function handle(Request $request, Closure $next, string $permission): mixed
    {
        $user = Guard::user();
        $userRoles = $this->getUserRoles($user['id']);
        
        $hasPermission = $this->checkHierarchicalPermission($userRoles, $permission);
        
        if (!$hasPermission) {
            return Response::json([
                'error' => 'Insufficient permissions',
                'required' => $permission,
                'user_roles' => $userRoles
            ], 403);
        }
        
        return $next($request);
    }
}
```

### Smart Caching Middleware

Cache inteligente baseado em contexto:

```php
class SmartCacheMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, Closure $next): mixed
    {
        if (!$this->shouldCache($request)) {
            return $next($request);
        }
        
        $cacheKey = $this->generateCacheKey($request);
        $cached = $this->cache->get($cacheKey);
        
        if ($cached) {
            return Response::json(json_decode($cached, true))
                          ->header('X-Cache', 'HIT');
        }
        
        $response = $next($request);
        
        if ($this->shouldCacheResponse($response)) {
            $ttl = $this->calculateTTL($request);
            $this->cache->put($cacheKey, $response->getContent(), $ttl);
        }
        
        return $response->header('X-Cache', 'MISS');
    }
    
    private function generateCacheKey(Request $request): string
    {
        $user = Guard::user();
        $context = [
            'url' => $request->getRequestUri(),
            'user_id' => $user['id'] ?? 'guest',
            'company_id' => $user['empresa'] ?? null,
            'modules' => $this->getActiveModules($user)
        ];
        
        return 'api:' . md5(serialize($context));
    }
}
```

## 🔧 Troubleshooting

### Problemas Comuns

#### 1. Middleware não é executado
```php
// Verificar se está registrado
$middlewareManager = app('middleware');
$aliases = $middlewareManager->getMiddlewareAliases();
var_dump($aliases); // Deve conter seu middleware

// Verificar configuração
$config = require 'Modules/Common/Config/middleware.php';
var_dump($config['aliases']); // Verificar aliases
```

#### 2. Token Guard não funciona
```php
// Debug de autenticação
Route::get('/debug/auth', function() {
    return Response::json([
        'headers' => $_SERVER,
        'token_extracted' => Guard::getTokenManager()->extractTokenFromRequest(),
        'user' => Guard::user(),
        'is_authenticated' => Guard::check()
    ]);
});
```

#### 3. Rate Limiting muito agressivo
```php
// Verificar configuração
$config = config('guard');
var_dump($config['rate_limiting']);

// Limpar cache de rate limiting
$cache = app('cache');
$cache->flush(); // CUIDADO: Remove todo o cache!
```

#### 4. Módulo não reconhecido
```php
// Verificar módulos disponíveis
$app = app('app');
$modules = $app->getAvailableModules();
var_dump($modules);

// Debug do middleware
Route::get('/debug/modules', function(Request $request) {
    $app = $request->officegestApplication();
    return Response::json([
        'has_ams' => $app->hasModule('AMS'),
        'has_wmso' => $app->hasModule('WMSO'),
        'has_vendas' => $app->hasModule('VENDAS'),
        'all_modules' => $app->getAllModules()
    ]);
});
```

### Logs e Debugging

```php
// Adicionar logging aos middlewares
class DebuggableMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, Closure $next): mixed
    {
        $startTime = microtime(true);
        
        error_log("Middleware " . static::class . " started for " . $request->getRequestUri());
        
        $response = $next($request);
        
        $duration = round((microtime(true) - $startTime) * 1000, 2);
        error_log("Middleware " . static::class . " completed in {$duration}ms");
        
        return $response;
    }
}
```

### Performance Monitoring

```php
class PerformanceMiddleware implements MiddlewareInterface
{
    public function handle(Request $request, Closure $next): mixed
    {
        $start = microtime(true);
        $memoryStart = memory_get_usage();
        
        $response = $next($request);
        
        $duration = round((microtime(true) - $start) * 1000, 2);
        $memoryUsed = memory_get_usage() - $memoryStart;
        
        $response->header('X-Response-Time', $duration . 'ms');
        $response->header('X-Memory-Usage', round($memoryUsed / 1024, 2) . 'KB');
        
        return $response;
    }
}
```

---

Esta documentação fornece uma base sólida para trabalhar com o sistema de middleware e Guard do OfficeGest, desde implementações básicas até padrões avançados para ERPs empresariais.