First Commit
This commit is contained in:
+147
@@ -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/');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user