First Commit

This commit is contained in:
marco
2026-09-01 10:46:29 -03:00
commit bf96b77e9c
10000 changed files with 3508600 additions and 0 deletions
+147
View File
@@ -0,0 +1,147 @@
<?php
namespace Modules\Company\Middleware;
use Closure;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
class CompanyMiddleware
{
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @return mixed
*/
public function handle(Request $request, Closure $next)
{
$user = $this->getCurrentUser();
if (!$user) {
return $this->unauthorizedResponse($request);
}
// Super Admin can access any company
if ($user->isSuperAdmin()) {
return $next($request);
}
// Routes that do not require a company context
$bypassRoutes = ['/profile', '/logout', '/dashboard'];
if (in_array($request->getPathInfo(), $bypassRoutes)) {
return $next($request);
}
// Get company ID from route or user session
$companyId = $this->getCompanyId($request, $user);
// Check if user can access the company
if (!$this->canAccessCompany($user, $companyId)) {
return $this->forbiddenResponse($request);
}
// Set company context in session for easy access
$_SESSION['current_company_id'] = $companyId;
return $next($request);
}
/**
* Get current authenticated user.
*
* @return \Modules\Auth\Models\User|null
*/
protected function getCurrentUser(): ?\Modules\Auth\Models\User
{
if (!isset($_SESSION['user_id'])) {
return null;
}
try {
if (class_exists('\Modules\Auth\Models\User')) {
return \Modules\Auth\Models\User::find($_SESSION['user_id']);
}
} catch (\Exception $e) {
error_log("Error loading user: " . $e->getMessage());
}
return null;
}
/**
* Get company ID from request or user session.
*
* @param Request $request
* @param \Modules\Auth\Models\User $user
* @return int|null
*/
protected function getCompanyId(Request $request, $user): ?int
{
// 1. Check URL parameter (if present)
// Note: FastRoute parameters are passed to controller, not easily accessible in middleware via standard request
// We can parse the path if necessary, but standard app logic usually relies on session or explicit selection.
// 2. Check Session
if (isset($_SESSION['current_company_id'])) {
return (int) $_SESSION['current_company_id'];
}
// 3. Default to user's primary business ID
return $user->users_bus_id;
}
/**
* Check if user can access the company.
*
* @param \Modules\Auth\Models\User $user
* @param int|null $companyId
* @return bool
*/
protected function canAccessCompany($user, $companyId): bool
{
if (!$companyId) {
return false;
}
// If user belongs to this company directly
if ($user->users_bus_id == $companyId) {
return true;
}
// If user has permission/association to this company (Multi-tenant logic)
// TODO: Implement multi-company association logic if needed
return false;
}
protected function unauthorizedResponse(Request $request)
{
if ($this->expectsJson($request)) {
return new JsonResponse(['message' => 'Unauthorized'], 401);
}
return new Response('', 302, ['Location' => url('/login')]);
}
protected function forbiddenResponse(Request $request)
{
if ($this->expectsJson($request)) {
return new JsonResponse(['message' => 'Forbidden - Access denied to this company'], 403);
}
// Show 403 error page
try {
$view = new \Kernel\View();
return new Response($view->render('errors/403.twig'), 403);
} catch (\Throwable $e) {
return new Response('Access denied to this company', 403);
}
}
protected function expectsJson(Request $request): bool
{
return $request->headers->get('Accept') === 'application/json' ||
$request->headers->get('Content-Type') === 'application/json' ||
str_contains($request->getPathInfo(), '/api/');
}
}