Files
bp/app/Filters/RoleFilter.php
T
2026-01-12 11:58:12 +03:00

101 lines
3.5 KiB
PHP

<?php
namespace App\Filters;
use App\Services\AccessService;
use CodeIgniter\Filters\FilterInterface;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
/**
* RoleFilter - Фильтр проверки ролей и прав доступа
*
* Применяется к маршрутам для проверки прав доступа на уровне роутинга.
*
* Использование в роутах:
* $routes->get('/admin/users', 'Users::index', ['filter' => 'role:admin']);
* $routes->get('/admin/settings', 'Settings::index', ['filter' => 'role:owner']);
*/
class RoleFilter implements FilterInterface
{
/**
* Проверка доступа перед выполнением запроса
*
* @param RequestInterface $request
* @param array|null $arguments Аргументы из маршрута (роли, разрешения)
* @return ResponseInterface|null
*/
public function before(RequestInterface $request, $arguments = null)
{
// Если фильтр вызван без аргументов - пропускаем
if ($arguments === null) {
return null;
}
$access = AccessService::getInstance();
// Проверка авторизации в организации
if (!$access->isAuthenticated()) {
// Если пользователь не авторизован в организации - редирект на выбор организации
return redirect()->to('/organizations');
}
// Разбор аргументов
// Формат: 'role:admin,manager' или 'permission:manage_users:users'
if (is_string($arguments) && str_starts_with($arguments, 'role:')) {
$roles = explode(',', substr($arguments, 5));
$roles = array_map('trim', $roles);
if (!$access->isRole($roles)) {
return $this->forbiddenResponse();
}
}
if (is_string($arguments) && str_starts_with($arguments, 'permission:')) {
$parts = explode(':', substr($arguments, 11));
if (count($parts) >= 2) {
$permission = $parts[0];
$resource = $parts[1] ?? '*';
if (!$access->can($permission, $resource)) {
return $this->forbiddenResponse();
}
}
}
return null;
}
/**
* Обработка после выполнения запроса
*
* @param RequestInterface $request
* @param ResponseInterface $response
* @param array|null $arguments
* @return void
*/
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
{
// Ничего не делаем после
}
/**
* Возврат ответа "Доступ запрещён"
*
* @return ResponseInterface
*/
private function forbiddenResponse(): ResponseInterface
{
// Проверяем, AJAX ли это запрос
if (service('request')->isAJAX()) {
return service('response')
->setStatusCode(403)
->setJSON(['error' => 'Доступ запрещён']);
}
// Для обычных запросов - редирект с сообщением
session()->setFlashdata('error', 'У вас нет прав для выполнения этого действия');
return redirect()->to('/');
}
}