Files
2026-09-01 10:46:29 -03:00

151 lines
4.2 KiB
PHP
Executable File

<?php
/**
* SysCMS - Content Management System
*
* Copyright (c) 2025 Marco Costa
* All rights reserved.
*
* Author: Marco Costa
* Email: contato@syspanel.com.br
* Project: SysCMS
*
* This software is licensed, not sold.
* Permission is granted to use this software
* subject to the terms of the SysCMS Commercial License.
*
* Redistribution, sublicensing, resale, or
* disclosure of this software, in whole or in part,
* is strictly prohibited without prior written permission.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.
*/
namespace App\Middlewares;
use Closure;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\JsonResponse;
class PermissionMiddleware
{
/**
* Handle an incoming request.
*
* @param Request $request
* @param Closure $next
* @param string $permission
* @return mixed
*/
public function handle(Request $request, Closure $next, string $permission)
{
$user = $this->getCurrentUser();
if (!$user) {
return $this->unauthorizedResponse($request);
}
// Check if user has the required permission
if (!$this->userHasPermission($user, $permission)) {
return $this->forbiddenResponse($request, $permission);
}
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 {
return \Modules\Auth\Models\User::find($_SESSION['user_id']);
} catch (\Exception $e) {
error_log("Error loading user: " . $e->getMessage());
return null;
}
}
/**
* Check if user has the required permission.
*
* @param \Modules\Auth\Models\User $user
* @param string $permission
* @return bool
*/
protected function userHasPermission(\Modules\Auth\Models\User $user, string $permission): bool
{
return $user->hasPermission($permission);
}
/**
* Create unauthorized response.
*
* @param Request $request
* @return Response
*/
protected function unauthorizedResponse(Request $request): Response
{
if ($this->expectsJson($request)) {
return new JsonResponse([
'success' => false,
'message' => __('auth.unauthenticated'),
'timestamp' => time()
], 401);
}
return new Response('', 302, [
'Location' => url('/login')
]);
}
/**
* Create forbidden response.
*
* @param Request $request
* @param string $permission
* @return Response
*/
protected function forbiddenResponse(Request $request, string $permission): Response
{
$message = __('auth.permission_denied', ['permission' => $permission]);
if ($this->expectsJson($request)) {
return new JsonResponse([
'success' => false,
'message' => $message,
'permission' => $permission,
'timestamp' => time()
], 403);
}
// For web requests, show error page
try {
$view = new \Kernel\View();
// We can pass the message to the view if we update the template
return new Response($view->render('errors/403.twig'), 403);
} catch (\Throwable $e) {
return new Response($message, 403);
}
}
/**
* Check if request expects JSON response.
*
* @param Request $request
* @return bool
*/
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/');
}
}