commit melhorias sgf
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Middleware;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Shared\Context\CompanyContext;
|
||||
use App\Shared\Context\RequireModuleContext;
|
||||
use Closure;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Session\ArraySessionHandler;
|
||||
use Illuminate\Session\Store;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
final class AuthenticateSgcInvoice
|
||||
{
|
||||
public function handle(Request $request, Closure $next)
|
||||
{
|
||||
abort_unless(config('sgc_invoice.enabled') === true, 404);
|
||||
// The installed native adapter is QA-only. This transport cannot remove that boundary.
|
||||
abort_unless(app()->environment('budget-testing'), 403);
|
||||
abort_unless($request->isSecure() || in_array($request->ip(), ['127.0.0.1', '::1'], true), 403);
|
||||
abort_if(strlen($request->getContent()) > 131072, 413);
|
||||
if ($request->isMethod('GET')) abort_if($request->query->count() || strlen($request->getContent()), 422);
|
||||
else abort_unless($request->isJson(), 415);
|
||||
$client = (string)$request->header('X-SGC-Client');
|
||||
$principals = config('sgc_invoice.principals', []);
|
||||
$principal = preg_match('/^[a-zA-Z0-9_-]{1,64}$/D', $client) ? ($principals[$client] ?? null) : null;
|
||||
$token = $request->bearerToken();
|
||||
abort_unless(is_array($principal) && ($principal['enabled'] ?? false) === true
|
||||
&& is_string($token) && strlen($token) >= 32 && strlen($token) <= 512
|
||||
&& preg_match('/^[a-f0-9]{64}$/D', $principal['token_sha256'] ?? '')
|
||||
&& hash_equals($principal['token_sha256'], hash('sha256', $token)), 401);
|
||||
foreach (['user_id', 'auth_version', 'tenant_id', 'company_id', 'unit_id'] as $key) {
|
||||
abort_unless(is_int($principal[$key] ?? null) && $principal[$key] > 0, 403);
|
||||
}
|
||||
$version = $principal['context_version'] ?? null;
|
||||
abort_unless(is_string($version) && preg_match('/^[a-f0-9]{64}$/D', $version)
|
||||
&& hash_equals($version, (string)$request->header('X-SGC-Context')), 409);
|
||||
$user = User::find($principal['user_id']);
|
||||
abort_unless($user && $user->auth_version === $principal['auth_version'], 401);
|
||||
$context = app(CompanyContext::class);
|
||||
$guard = Auth::getDefaultDriver();
|
||||
$oldUser = Auth::guard($guard)->user();
|
||||
$oldResolver = $request->getUserResolver();
|
||||
$oldSession = $request->hasSession() ? $request->session() : null;
|
||||
try {
|
||||
// Context and person come exclusively from the server-side principal, never JSON/cookies.
|
||||
$context->selectFor($user->id, $principal['tenant_id'], $principal['company_id'], $principal['unit_id']);
|
||||
Auth::guard($guard)->setUser($user);
|
||||
$request->setUserResolver(fn () => $user);
|
||||
$session = new Store('sgc_invoice_ephemeral', new ArraySessionHandler(10));
|
||||
$session->start();
|
||||
$session->put('company_context', ['tenant_id'=>$principal['tenant_id'], 'company_id'=>$principal['company_id'],
|
||||
'unit_id'=>$principal['unit_id'], 'module_id'=>'purchasing', 'token'=>$version]);
|
||||
$request->setLaravelSession($session);
|
||||
$request->headers->set('X-SGF-Context', $version);
|
||||
app(RequireModuleContext::class)->check($request, $context);
|
||||
$response = $next($request);
|
||||
$response->headers->set('Cache-Control', 'no-store, private');
|
||||
return $response;
|
||||
} finally {
|
||||
$context->clear();
|
||||
if (isset($session)) $session->flush();
|
||||
Auth::forgetGuards(); Auth::shouldUse($guard);
|
||||
if ($oldUser) Auth::guard($guard)->setUser($oldUser);
|
||||
$request->setUserResolver($oldResolver);
|
||||
if ($oldSession) $request->setLaravelSession($oldSession);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user