add superadmin dashboard. subscriptions
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filters;
|
||||
|
||||
use App\Controllers\Auth;
|
||||
use App\Models\UserModel;
|
||||
use App\Models\OrganizationUserModel;
|
||||
use CodeIgniter\Filters\FilterInterface;
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
|
||||
/**
|
||||
* AuthFilter - Фильтр аутентификации с поддержкой Remember Me
|
||||
*
|
||||
* Проверяет авторизацию пользователя двумя способами:
|
||||
* 1. По сессии (стандартный способ)
|
||||
* 2. По remember-токену из cookies (если сессия отсутствует)
|
||||
*
|
||||
* Если пользователь не авторизован — редирект на /login.
|
||||
*
|
||||
* Применяется к маршрутам, которые требуют авторизации, но НЕ требуют
|
||||
* выбранной организации (например, профиль, выбор организации).
|
||||
*/
|
||||
class AuthFilter implements FilterInterface
|
||||
{
|
||||
/**
|
||||
* Проверка аутентификации перед обработкой запроса
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param array|null $arguments
|
||||
* @return ResponseInterface|void
|
||||
*/
|
||||
public function before(RequestInterface $request, $arguments = null)
|
||||
{
|
||||
$session = session();
|
||||
|
||||
// Если пользователь уже авторизован по сессии — пропускаем
|
||||
if ($session->get('isLoggedIn')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Проверяем remember-токен
|
||||
$userId = Auth::checkRememberToken();
|
||||
|
||||
if ($userId !== null) {
|
||||
// Токен найден и валиден — восстанавливаем сессию
|
||||
$userModel = new UserModel();
|
||||
$user = $userModel->find($userId);
|
||||
|
||||
if ($user && $user['email_verified']) {
|
||||
$orgUserModel = new OrganizationUserModel();
|
||||
$userOrgs = $orgUserModel->where('user_id', $user['id'])->findAll();
|
||||
|
||||
if (!empty($userOrgs)) {
|
||||
// Восстанавливаем данные сессии
|
||||
$sessionData = [
|
||||
'user_id' => $user['id'],
|
||||
'email' => $user['email'],
|
||||
'name' => $user['name'],
|
||||
'isLoggedIn' => true,
|
||||
];
|
||||
|
||||
// Выбираем организацию если она была
|
||||
if (count($userOrgs) === 1) {
|
||||
$sessionData['active_org_id'] = $userOrgs[0]['organization_id'];
|
||||
}
|
||||
|
||||
$session->set($sessionData);
|
||||
|
||||
log_message('info', "User {$user['email']} logged in via remember token");
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Токен недействителен — удаляем его
|
||||
$response = service('response');
|
||||
$response->deleteCookie('remember_selector');
|
||||
$response->deleteCookie('remember_token');
|
||||
}
|
||||
|
||||
// Пользователь не авторизован — редирект на логин
|
||||
return redirect()->to('/login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Обработка после выполнения запроса
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param ResponseInterface $response
|
||||
* @param array|null $arguments
|
||||
* @return void
|
||||
*/
|
||||
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void
|
||||
{
|
||||
// Ничего не делаем после запроса
|
||||
}
|
||||
}
|
||||
@@ -6,74 +6,47 @@ use CodeIgniter\Filters\FilterInterface;
|
||||
use CodeIgniter\HTTP\RequestInterface;
|
||||
use CodeIgniter\HTTP\ResponseInterface;
|
||||
|
||||
/**
|
||||
* OrganizationFilter - Фильтр выбора организации
|
||||
*
|
||||
* Проверяет, что у авторизованного пользователя выбрана организация.
|
||||
* Если организация не выбрана — редирект на /organizations.
|
||||
*
|
||||
* Применяется к маршрутам, которые требуют выбранной организации
|
||||
* (например, дашборд, управление клиентами, задачи и т.д.).
|
||||
*/
|
||||
class OrganizationFilter implements FilterInterface
|
||||
{
|
||||
|
||||
/**
|
||||
* Проверка выбора организации перед обработкой запроса
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param array|null $arguments
|
||||
* @return ResponseInterface|void
|
||||
*/
|
||||
public function before(RequestInterface $request, $arguments = null)
|
||||
{
|
||||
$session = session();
|
||||
$uri = $request->getUri();
|
||||
$currentPath = $uri->getPath();
|
||||
|
||||
// === БЛОК ДЛЯ ГОСТЕЙ (НЕЗАЛОГИНЕННЫХ) ===
|
||||
if (!$session->get('isLoggedIn')) {
|
||||
// Список публичных маршрутов для гостей
|
||||
$publicRoutes = [
|
||||
'/',
|
||||
'/login',
|
||||
'/register',
|
||||
'/register/success',
|
||||
'/auth/verify',
|
||||
'/auth/resend-verification',
|
||||
];
|
||||
|
||||
if (!in_array($currentPath, $publicRoutes)) {
|
||||
// Если гость лезет не туда (например /organizations) — на главную
|
||||
return redirect()->to('/');
|
||||
}
|
||||
// Иначе пропускаем
|
||||
return;
|
||||
}
|
||||
// =======================================
|
||||
|
||||
// === БЛОК ДЛЯ ЗАЛОГИНЕННЫХ ===
|
||||
|
||||
// Список маршрутов, доступных БЕЗ выбранной организации
|
||||
$publicAuthRoutes = [
|
||||
'/login',
|
||||
'/register',
|
||||
'/logout',
|
||||
'/register/success',
|
||||
'/auth/verify',
|
||||
'/auth/resend-verification',
|
||||
'/organizations',
|
||||
'/organizations/create',
|
||||
'/organizations/switch' // Начало пути для переключения
|
||||
];
|
||||
|
||||
// Если мы на этих маршрутах — проверка orgId не нужна (мы просто выбираем её)
|
||||
if (in_array($currentPath, $publicAuthRoutes) || strpos($currentPath, '/organizations/switch') === 0) {
|
||||
// Если пользователь не авторизован — пропускаем (AuthFilter разберётся)
|
||||
if (!session()->get('isLoggedIn')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Если мы попадаем сюда — значит пользователь идет на закрытую страницу (например /crm)
|
||||
// или на главную (/).
|
||||
|
||||
// Главную страницу (/) мы проверяем на уровне контроллера Home::index,
|
||||
// поэтому фильтр для '/' можно пропускать, ИЛИ проверить здесь.
|
||||
// Пропустим '/', чтобы контроллер сам решил: редиректить на /organizations или показывать дашборд.
|
||||
if ($currentPath === '/') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Для всех остальных закрытых страниц проверяем active_org_id
|
||||
// Проверяем, выбрана ли организация
|
||||
if (empty(session()->get('active_org_id'))) {
|
||||
return redirect()->to('/organizations');
|
||||
}
|
||||
}
|
||||
|
||||
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null)
|
||||
/**
|
||||
* Обработка после выполнения запроса
|
||||
*
|
||||
* @param RequestInterface $request
|
||||
* @param ResponseInterface $response
|
||||
* @param array|null $arguments
|
||||
* @return void
|
||||
*/
|
||||
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): void
|
||||
{
|
||||
// Do nothing
|
||||
// Ничего не делаем после запроса
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,24 +34,43 @@ class RoleFilter implements FilterInterface
|
||||
|
||||
$access = AccessService::getInstance();
|
||||
|
||||
// Проверка авторизации в организации
|
||||
if (!$access->isAuthenticated()) {
|
||||
// Если пользователь не авторизован в организации - редирект на выбор организации
|
||||
return redirect()->to('/organizations');
|
||||
// Разбор аргументов
|
||||
// Формат: 'role:admin,manager' или 'role:system:superadmin' или 'permission:manage_users:users'
|
||||
|
||||
// Проверка системных ролей (system: prefix)
|
||||
if (is_string($arguments) && str_starts_with($arguments, 'role:system:')) {
|
||||
$roles = explode(',', substr($arguments, 13)); // 13 = длина 'role:system:'
|
||||
$roles = array_map('trim', $roles);
|
||||
|
||||
// Для системных ролей НЕ требуется авторизация в организации
|
||||
if (!$access->isSystemRole($roles)) {
|
||||
return $this->forbiddenResponse();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Разбор аргументов
|
||||
// Формат: '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->isAuthenticated()) {
|
||||
// Если пользователь не авторизован в организации - редирект на выбор организации
|
||||
return redirect()->to('/organizations');
|
||||
}
|
||||
|
||||
if (!$access->isRole($roles)) {
|
||||
return $this->forbiddenResponse();
|
||||
}
|
||||
}
|
||||
|
||||
if (is_string($arguments) && str_starts_with($arguments, 'permission:')) {
|
||||
// Проверка авторизации в организации для разрешений
|
||||
if (!$access->isAuthenticated()) {
|
||||
return redirect()->to('/organizations');
|
||||
}
|
||||
|
||||
$parts = explode(':', substr($arguments, 11));
|
||||
if (count($parts) >= 2) {
|
||||
$permission = $parts[0];
|
||||
|
||||
Reference in New Issue
Block a user