$user['login'], 'ts' => time() ]; $json = json_encode($payloadArr, JSON_UNESCAPED_SLASHES); $sig = hash_hmac('sha256', $json, self::APP_SECRET_KEY); $payload = base64_encode($json . '.' . $sig); setcookie( $cookie_name, $payload, [ 'expires' => time() + (86400 * 14), 'path' => '/', 'domain' => $domain, 'secure' => true, 'httponly' => true, 'samesite' => 'Lax', ]); } } public static function special_actions() { global $mdb; $sa = \S::get('s-action'); $domain = preg_replace('/^www\./', '', $_SERVER['SERVER_NAME']); $cookie_name = 'admin_remember_' . str_replace( '.', '-', $domain ); $users = new \Domain\User\UserRepository($mdb); switch ($sa) { case 'user-logon': { $login = \S::get('login'); $pass = \S::get('password'); $result = $users->logon($login, $pass); if ( $result == 1 ) { $user = $users->details($login); if ( $user['twofa_enabled'] == 1 ) { \S::set_session( 'twofa_pending', [ 'uid' => (int)$user['id'], 'login' => $login, 'remember' => (bool)\S::get('remember'), 'started' => time(), ] ); if ( !$users->sendTwofaCode( (int)$user['id'] ) ) { \S::alert('Nie udało się wysłać kodu 2FA. Spróbuj ponownie.'); \S::delete_session('twofa_pending'); header('Location: /admin/'); exit; } header('Location: /admin/user/twofa/'); exit; } else { $user = $users->details($login); self::finalize_admin_login( $user, $domain, $cookie_name, (bool)\S::get('remember') ); header('Location: /admin/articles/view_list/'); exit; } } else { if ($result == -1) { \S::alert('Z powodu 5 nieudanych prób Twoje konto zostało zablokowane.'); } else { \S::alert('Podane hasło jest nieprawidłowe lub użytkownik nie istnieje.'); } header('Location: /admin/'); exit; } } break; case 'user-2fa-verify': { $pending = \S::get_session('twofa_pending'); if ( !$pending || empty( $pending['uid'] ) ) { \S::alert('Sesja 2FA wygasła. Zaloguj się ponownie.'); header('Location: /admin/'); exit; } $code = trim((string)\S::get('twofa')); if (!preg_match('/^\d{6}$/', $code)) { \S::alert('Nieprawidłowy format kodu.'); header('Location: /admin/user/twofa/'); exit; } $ok = $users->verifyTwofaCode((int)$pending['uid'], $code); if (!$ok) { \S::alert('Błędny lub wygasły kod.'); header('Location: /admin/user/twofa/'); exit; } // 2FA OK — finalna sesja $user = $users->details($pending['login']); self::finalize_admin_login( $user, $domain, $cookie_name, $pending['remember'] ? true : false ); header('Location: /admin/articles/view_list/'); exit; } break; case 'user-2fa-resend': { $pending = \S::get_session('twofa_pending'); if (!$pending || empty($pending['uid'])) { \S::alert('Sesja 2FA wygasła. Zaloguj się ponownie.'); header('Location: /admin/'); exit; } if (!$users->sendTwofaCode((int)$pending['uid'], true)) { \S::alert('Kod można wysłać ponownie po krótkiej przerwie.'); } else { \S::alert('Nowy kod został wysłany.'); } header('Location: /admin/user/twofa/'); exit; } break; case 'user-logout': { setcookie($cookie_name, "", [ 'expires' => time() - 86400, 'path' => '/', 'domain' => $domain, 'secure' => true, 'httponly' => true, 'samesite' => 'Lax', ]); \S::delete_session('twofa_pending'); session_destroy(); header('Location: /admin/'); exit; } break; } } /** * Mapa nowych kontrolerów: module => fabryka kontrolera (DI) * Przy migracji kolejnego kontrolera - dodaj wpis tutaj */ private static $newControllers = []; /** * Zwraca mapę fabryk kontrolerów (inicjalizacja runtime) */ private static function getControllerFactories(): array { if ( !empty( self::$newControllers ) ) return self::$newControllers; self::$newControllers = [ 'Articles' => function() { global $mdb; return new \admin\Controllers\ArticlesController( new \Domain\Article\ArticleRepository( $mdb ) ); }, 'Banners' => function() { global $mdb; return new \admin\Controllers\BannerController( new \Domain\Banner\BannerRepository( $mdb ) ); }, 'Settings' => function() { global $mdb; return new \admin\Controllers\SettingsController( new \Domain\Settings\SettingsRepository( $mdb ) ); }, 'ProductArchive' => function() { global $mdb; return new \admin\Controllers\ProductArchiveController( new \Domain\Product\ProductRepository( $mdb ) ); }, // Alias dla starego modułu /admin/archive/products_list/ 'Archive' => function() { global $mdb; return new \admin\Controllers\ProductArchiveController( new \Domain\Product\ProductRepository( $mdb ) ); }, 'Dictionaries' => function() { global $mdb; return new \admin\Controllers\DictionariesController( new \Domain\Dictionaries\DictionariesRepository( $mdb ) ); }, 'Filemanager' => function() { return new \admin\Controllers\FilemanagerController(); }, 'Users' => function() { global $mdb; return new \admin\Controllers\UsersController( new \Domain\User\UserRepository( $mdb ) ); }, ]; return self::$newControllers; } /** * Tworzy instancję nowego kontrolera z Dependency Injection */ private static function createController( string $moduleName ) { global $mdb; $factories = self::getControllerFactories(); if ( !isset( $factories[$moduleName] ) ) return null; $factory = $factories[$moduleName]; if ( !is_callable( $factory ) ) return null; return $factory(); } /** * Mapowanie nazw akcji: stara_nazwa => nowa_nazwa * Potrzebne gdy stary routing używa innej konwencji nazw */ private static $actionMap = [ 'gallery_order_save' => 'galleryOrderSave', 'view_list' => 'list', 'article_edit' => 'edit', 'article_save' => 'save', 'article_delete' => 'delete', 'banner_edit' => 'edit', 'banner_save' => 'save', 'banner_delete' => 'delete', 'clear_cache' => 'clearCache', 'clear_cache_ajax' => 'clearCacheAjax', 'settings_save' => 'save', 'products_list' => 'list', 'unit_edit' => 'edit', 'unit_save' => 'save', 'unit_delete' => 'delete', ]; public static function route() { $_SESSION['admin'] = true; if ( \S::get( 'p' ) ) \S::set_session( 'p' , \S::get( 'p' ) ); $page = \S::get_session( 'p' ); // Budowanie nazwy modułu $moduleName = ''; $results = explode( '_', \S::get( 'module' ) ); if ( is_array( $results ) ) foreach ( $results as $row ) $moduleName .= ucfirst( $row ); $action = \S::get( 'action' ); // 1. Sprawdź czy istnieje nowy kontroler $factories = self::getControllerFactories(); if ( isset( $factories[$moduleName] ) ) { $controller = self::createController( $moduleName ); if ( $controller ) { // Mapuj nazwę akcji (stara → nowa) lub użyj oryginalnej $newAction = self::$actionMap[$action] ?? $action; if ( method_exists( $controller, $newAction ) ) { return $controller->$newAction(); } } } // 2. Fallback na stary kontroler $class = '\admin\controls\\' . $moduleName; if ( class_exists( $class ) and method_exists( new $class, $action ) ) return call_user_func_array( array( $class, $action ), array() ); else { \S::alert( 'Nieprawidłowy adres url.' ); return false; } } static public function update() { global $mdb; if ( $results = $mdb -> select( 'pp_updates', [ 'name' ], [ 'done' => 0 ] ) ) { foreach ( $results as $row ) { $class = '\admin\factory\Update'; $method = $row['name']; if ( class_exists( $class ) and method_exists( new $class, $method ) ) call_user_func_array( array( $class, $method ), array() ); } } } }