367 lines
9.4 KiB
PHP
367 lines
9.4 KiB
PHP
<?php
|
|
namespace admin;
|
|
|
|
class Site
|
|
{
|
|
// define APP_SECRET_KEY
|
|
const APP_SECRET_KEY = 'c3cb2537d25c0efc9e573d059d79c3b8';
|
|
|
|
static public function finalize_admin_login( array $user, string $domain, string $cookie_name, bool $remember = false ) {
|
|
|
|
\S::set_session( 'user', $user );
|
|
\S::delete_session( 'twofa_pending' );
|
|
|
|
if ( $remember ) {
|
|
$payloadArr = [
|
|
'login' => $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() );
|
|
}
|
|
}
|
|
}
|
|
}
|