Phalcon Framework 5.10.0

PDOException: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: NO)

/home/laberitillusions/public_html/apps/config/services.php (91)
#0PDO->__construct(mysql:charset=utf8;host=localhost;dbname=factorial_laberit_local, root, , Array([20] => , [17] => , [3] => 2))
#1Phalcon\Db\Adapter\Pdo\AbstractPdo->connect(Array([host] => localhost, [username] => root, [password] => (empty string), [dbname] => factorial_laberit_local, [charset] => utf8, [options] => Array([20] => , [17] => )))
#2Phalcon\Db\Adapter\Pdo\AbstractPdo->__construct(Array([host] => localhost, [username] => root, [password] => (empty string), [dbname] => factorial_laberit_local, [charset] => utf8, [options] => Array([20] => , [17] => )))
/home/laberitillusions/public_html/apps/config/services.php (91)
<?php
 
namespace illusion;
 
use Common\Libraries\Translate\DbAdapter;
use illusion\Common\Acl\Acl;
use illusion\Common\Auth\Auth;
use illusion\Common\Models\Info;
use illusion\Common\Models\Languages;
use illusion\Common\Plugins\ForwardPlugin;
use illusion\Common\Plugins\NotFoundPlugin;
use illusion\Common\Plugins\SecurityHeadersPlugin;
use illusion\Common\Plugins\SecurityPlugin;
use illusion\Common\Utils\Utils;
use illusion\Mail\Mail;
use Phalcon\Encryption\Crypt;
use Phalcon\Db\Adapter\Pdo\Mysql as Connection;
use Phalcon\DI\Di;
use Phalcon\DI\FactoryDefault;
use Phalcon\Flash\Session as FlashSession;
use Phalcon\Html\Escaper;
use Phalcon\Http\Request;
use Phalcon\Http\Response\Cookies;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\Model\Metadata\Files as MetaDataAdapter;
use Phalcon\Mvc\Url as UrlResolver;
use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Volt;
use Phalcon\Session\Adapter\Stream as SessionAdapter;
use Phalcon\Session\Manager as SessionManager;
use ReflectionClass;
use ReflectionMethod;
 
//use Phalcon\Flash\Direct as Flash;
 
 
/**
 * The FactoryDefault Dependency Injector automatically register the right services providing a full stack framework
 */
$di = new FactoryDefault();
 
 
/**
 * Register the global configuration as config
 */
$di->set('config', $config);
 
/**
 * Loading routes from the routes.php file
 */
$di->set('router', function () use ($config) {
    return require APPS_DIR . '/config/routes.php';
});
 
 
/**
 * The URL component is used to generate all kind of urls in the application
 */
$di->set('url', function () use ($config) {
    $url = new UrlResolver();
    $url->setBaseUri($config->application->publicUrl . $config->application->baseUri);
    return $url;
}, true);
 
/**
 * Setting up the view component
 */
$di->set('view', function () use ($config) {
    $view = new View();
    $view->setViewsDir(CACHE_DIR . '/volt/');
    $view->registerEngines(['.volt' => function ($view) use ($config) {
        $volt = new Volt($view, $this);
        $volt->setOptions([
            'path' => CACHE_DIR . '/volt/',
            'separator' => '_',
            'always' => false
        ]); #options
        return $volt;
    }
    ]); #engines
    return $view;
}, true);
 
/**
 * Database connection is created based in the parameters defined in the configuration file
 */
$di->set('db', function () use ($config) {
 
    $connection = new Connection(
        array(
            "host" => $config->database->host,
            "username" => $config->database->username,
            "password" => $config->database->password,
            "dbname" => $config->database->dbname,
            "charset" => $config->database->charset,
            'options' => [
                \PDO::ATTR_EMULATE_PREPARES => false,
                \PDO::ATTR_STRINGIFY_FETCHES => false,
            ],
        )
    );
 
    return $connection;
});
 
if (APPLICATION_ENV == 'pro') {
    $di->set('modelsMetadata', function () use ($config) {
        return new MetaDataAdapter([
            'metaDataDir' => CACHE_DIR . '/metaData/'
        ]);
    });
}
 
/**
 * Start the session the first time some component request the session service
 */
$di->set('session', function () {
    $adapter = new SessionAdapter();
    $session = new SessionManager();
    $session->setAdapter($adapter);
//    $session = new SessionAdapter();
    $session->start();
    return $session;
});
 
$di->set('cookies', function () {
    $cookies = new Cookies();
    // Requiere el servicio 'crypt' (ya registrado abajo). Cifra valor de cookies a nivel app.
    $cookies->useEncryption(true);
    return $cookies;
});
 
/**
 * Crypt service
 */
$di->set('crypt', function () use ($config) {
    $crypt = new Crypt();
    $crypt->setKey($config->application->cryptSalt);
    return $crypt;
});
 
$di->set('dispatcher', function () use ($di) {
 
    $evManager = $di->getShared('eventsManager');
    $evManager->attach('dispatch:beforeDispatch', new SecurityPlugin);
    $evManager->attach('dispatch:afterDispatchLoop', new SecurityHeadersPlugin);
    $evManager->attach('dispatch:beforeException', new NotFoundPlugin);
    $evManager->attach('dispatch:beforeForward', new ForwardPlugin);
 
    $dispatcher = new Dispatcher();
 
    $dispatcher->setEventsManager($evManager);
    return $dispatcher;
}, true);
 
 
/**
 * Flash service with custom CSS classes
 */
$di->set('flash', function () {
    $flash = new FlashSession();
    $flash->setCssClasses([
        'success' => 'alert alert-success alert-dismissable fade in',
        'notice' => 'alert alert-info alert-dismissable fade in',
        'warning' => 'alert alert-warning alert-dismissable fade in',
        'error' => 'alert alert-danger alert-dismissable fade in'
    ]);
    return $flash;
});
 
/**
 * Custom authentication component
 */
$di->setShared('auth', function () {
    return new Auth();
});
 
$di->setShared('utils', function () {
    return new Utils();
});
 
/**
 * Access Control List
 */
$di->set('acl', function () {
    return new Acl();
});
/**
 * Access Control List
 */
$di->setShared('mobiledetect', function () {
    return new \Mobile_Detect();
});
 
 
$di->setShared('t', function ($lang = false) use ($config, $di) {
 
    global $lang;
    $request = new Request();
    $language = DI::getDefault()->getShared('auth')->getActiveLanguage();
 
    if (!$language) {
        $lang = $request->getBestLanguage();
        if (!$lang) {
            $lang = 'es';
        }
 
       $language = Languages::findFirstByLang($lang);
        if (!$language) {
            $lang = 'es';
        } else {
            $lang = $language->lang;
        }
    } else {
        $lang = $language->lang;
    }
 
    $db = $di->getDefault()->getDb();
 
 
    return new DbAdapter([
        'db'          => $db,
        'table'       => 'translations',
        'language'    => 'language',
        'key'         => 'key_name',
        'value'       => 'value',
        'locale'      => $lang,
    ]);
 
 
});
 
 
$di->setShared('request', function () {
    return new Request();
});
 
 
/*
 * Marcando como shared el modulo al cargalo esto deja disponibles las "cosicas"
*/
foreach ($config->modules as $module) {
    $dir = preg_replace("/\/Module.php$/", "", $module['path']);
    // Register Namespace for Shared Module (will not be called by dispatch)
 
    if (isset($module['shared'])) {
        $namespace = preg_replace('/\\\Module$/', "", $module['className']);
        $loader->setNamespaces(array($namespace => $dir), true);
        // Loading Module class bootloader Reflection Instance
        $reflexion = new ReflectionClass($module['className']);
        $instance = $reflexion->newInstanceWithoutConstructor();
        // Execute every 'register' methods
        foreach ($reflexion->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
            if (preg_match('/^register/', $method->name)) {
                $instance->{$method->name}($di);
            }
        }
    }
}
#3Closure->illusion\{closure}()
#4Phalcon\Di\Service->resolve(null, Object(Phalcon\Di\FactoryDefault))
#5Phalcon\Di\Di->get(db, null)
#6Phalcon\Di\Di->getShared(db)
#7Phalcon\Mvc\Model\Manager->getConnection(Object(illusion\Common\Models\Languages: 30), Array())
#8Phalcon\Mvc\Model\Manager->getReadConnection(Object(illusion\Common\Models\Languages: 30))
#9Phalcon\Mvc\Model->getReadConnection()
#10Phalcon\Mvc\Model\MetaData\Strategy\Introspection->getMetaData(Object(illusion\Common\Models\Languages: 30), Object(Phalcon\Di\FactoryDefault))
#11Phalcon\Mvc\Model\MetaData->initializeMetaData(Object(illusion\Common\Models\Languages: 30), illusion\common\models\languages)
#12Phalcon\Mvc\Model\MetaData->getMetaDataUniqueKey(Object(illusion\Common\Models\Languages: 30))
#13Phalcon\Mvc\Model\MetaData->readMetaDataIndex(Object(illusion\Common\Models\Languages: 30), 4)
#14Phalcon\Mvc\Model\MetaData->getDataTypes(Object(illusion\Common\Models\Languages: 30))
#15Phalcon\Mvc\Model::invokeFinder(findFirstByLang, Array([0] => es))
#16Phalcon\Mvc\Model::__callStatic(findFirstByLang, Array([0] => es))
/home/laberitillusions/public_html/apps/config/services.php (208)
<?php
 
namespace illusion;
 
use Common\Libraries\Translate\DbAdapter;
use illusion\Common\Acl\Acl;
use illusion\Common\Auth\Auth;
use illusion\Common\Models\Info;
use illusion\Common\Models\Languages;
use illusion\Common\Plugins\ForwardPlugin;
use illusion\Common\Plugins\NotFoundPlugin;
use illusion\Common\Plugins\SecurityHeadersPlugin;
use illusion\Common\Plugins\SecurityPlugin;
use illusion\Common\Utils\Utils;
use illusion\Mail\Mail;
use Phalcon\Encryption\Crypt;
use Phalcon\Db\Adapter\Pdo\Mysql as Connection;
use Phalcon\DI\Di;
use Phalcon\DI\FactoryDefault;
use Phalcon\Flash\Session as FlashSession;
use Phalcon\Html\Escaper;
use Phalcon\Http\Request;
use Phalcon\Http\Response\Cookies;
use Phalcon\Mvc\Dispatcher;
use Phalcon\Mvc\Model\Metadata\Files as MetaDataAdapter;
use Phalcon\Mvc\Url as UrlResolver;
use Phalcon\Mvc\View;
use Phalcon\Mvc\View\Engine\Volt;
use Phalcon\Session\Adapter\Stream as SessionAdapter;
use Phalcon\Session\Manager as SessionManager;
use ReflectionClass;
use ReflectionMethod;
 
//use Phalcon\Flash\Direct as Flash;
 
 
/**
 * The FactoryDefault Dependency Injector automatically register the right services providing a full stack framework
 */
$di = new FactoryDefault();
 
 
/**
 * Register the global configuration as config
 */
$di->set('config', $config);
 
/**
 * Loading routes from the routes.php file
 */
$di->set('router', function () use ($config) {
    return require APPS_DIR . '/config/routes.php';
});
 
 
/**
 * The URL component is used to generate all kind of urls in the application
 */
$di->set('url', function () use ($config) {
    $url = new UrlResolver();
    $url->setBaseUri($config->application->publicUrl . $config->application->baseUri);
    return $url;
}, true);
 
/**
 * Setting up the view component
 */
$di->set('view', function () use ($config) {
    $view = new View();
    $view->setViewsDir(CACHE_DIR . '/volt/');
    $view->registerEngines(['.volt' => function ($view) use ($config) {
        $volt = new Volt($view, $this);
        $volt->setOptions([
            'path' => CACHE_DIR . '/volt/',
            'separator' => '_',
            'always' => false
        ]); #options
        return $volt;
    }
    ]); #engines
    return $view;
}, true);
 
/**
 * Database connection is created based in the parameters defined in the configuration file
 */
$di->set('db', function () use ($config) {
 
    $connection = new Connection(
        array(
            "host" => $config->database->host,
            "username" => $config->database->username,
            "password" => $config->database->password,
            "dbname" => $config->database->dbname,
            "charset" => $config->database->charset,
            'options' => [
                \PDO::ATTR_EMULATE_PREPARES => false,
                \PDO::ATTR_STRINGIFY_FETCHES => false,
            ],
        )
    );
 
    return $connection;
});
 
if (APPLICATION_ENV == 'pro') {
    $di->set('modelsMetadata', function () use ($config) {
        return new MetaDataAdapter([
            'metaDataDir' => CACHE_DIR . '/metaData/'
        ]);
    });
}
 
/**
 * Start the session the first time some component request the session service
 */
$di->set('session', function () {
    $adapter = new SessionAdapter();
    $session = new SessionManager();
    $session->setAdapter($adapter);
//    $session = new SessionAdapter();
    $session->start();
    return $session;
});
 
$di->set('cookies', function () {
    $cookies = new Cookies();
    // Requiere el servicio 'crypt' (ya registrado abajo). Cifra valor de cookies a nivel app.
    $cookies->useEncryption(true);
    return $cookies;
});
 
/**
 * Crypt service
 */
$di->set('crypt', function () use ($config) {
    $crypt = new Crypt();
    $crypt->setKey($config->application->cryptSalt);
    return $crypt;
});
 
$di->set('dispatcher', function () use ($di) {
 
    $evManager = $di->getShared('eventsManager');
    $evManager->attach('dispatch:beforeDispatch', new SecurityPlugin);
    $evManager->attach('dispatch:afterDispatchLoop', new SecurityHeadersPlugin);
    $evManager->attach('dispatch:beforeException', new NotFoundPlugin);
    $evManager->attach('dispatch:beforeForward', new ForwardPlugin);
 
    $dispatcher = new Dispatcher();
 
    $dispatcher->setEventsManager($evManager);
    return $dispatcher;
}, true);
 
 
/**
 * Flash service with custom CSS classes
 */
$di->set('flash', function () {
    $flash = new FlashSession();
    $flash->setCssClasses([
        'success' => 'alert alert-success alert-dismissable fade in',
        'notice' => 'alert alert-info alert-dismissable fade in',
        'warning' => 'alert alert-warning alert-dismissable fade in',
        'error' => 'alert alert-danger alert-dismissable fade in'
    ]);
    return $flash;
});
 
/**
 * Custom authentication component
 */
$di->setShared('auth', function () {
    return new Auth();
});
 
$di->setShared('utils', function () {
    return new Utils();
});
 
/**
 * Access Control List
 */
$di->set('acl', function () {
    return new Acl();
});
/**
 * Access Control List
 */
$di->setShared('mobiledetect', function () {
    return new \Mobile_Detect();
});
 
 
$di->setShared('t', function ($lang = false) use ($config, $di) {
 
    global $lang;
    $request = new Request();
    $language = DI::getDefault()->getShared('auth')->getActiveLanguage();
 
    if (!$language) {
        $lang = $request->getBestLanguage();
        if (!$lang) {
            $lang = 'es';
        }
 
       $language = Languages::findFirstByLang($lang);
        if (!$language) {
            $lang = 'es';
        } else {
            $lang = $language->lang;
        }
    } else {
        $lang = $language->lang;
    }
 
    $db = $di->getDefault()->getDb();
 
 
    return new DbAdapter([
        'db'          => $db,
        'table'       => 'translations',
        'language'    => 'language',
        'key'         => 'key_name',
        'value'       => 'value',
        'locale'      => $lang,
    ]);
 
 
});
 
 
$di->setShared('request', function () {
    return new Request();
});
 
 
/*
 * Marcando como shared el modulo al cargalo esto deja disponibles las "cosicas"
*/
foreach ($config->modules as $module) {
    $dir = preg_replace("/\/Module.php$/", "", $module['path']);
    // Register Namespace for Shared Module (will not be called by dispatch)
 
    if (isset($module['shared'])) {
        $namespace = preg_replace('/\\\Module$/', "", $module['className']);
        $loader->setNamespaces(array($namespace => $dir), true);
        // Loading Module class bootloader Reflection Instance
        $reflexion = new ReflectionClass($module['className']);
        $instance = $reflexion->newInstanceWithoutConstructor();
        // Execute every 'register' methods
        foreach ($reflexion->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
            if (preg_match('/^register/', $method->name)) {
                $instance->{$method->name}($di);
            }
        }
    }
}
#17Closure->illusion\{closure}()
#18Phalcon\Di\Service->resolve(null, Object(Phalcon\Di\FactoryDefault))
#19Phalcon\Di\Di->get(t, null)
#20Phalcon\Di\Di->getShared(t)
#21Phalcon\Di\Injectable->__get(t)
/home/laberitillusions/public_html/apps/modules/users/controllers/AuthController.php (36)
<?php
 
namespace illusion\Modules\Users\Controllers;
 
use illusion\Common\Auth\Exception;
use illusion\Common\TwoFactor\TwoFactorService;
use illusion\Modules\Users\Forms\ConfirmaccountForm;
use illusion\Modules\Users\Forms\ForgotPasswordForm;
use illusion\Modules\Users\Forms\LoginForm;
use illusion\Modules\Users\Forms\PasswordForm;
use illusion\Modules\Users\Models\FailedLoginsData;
use illusion\Modules\Users\Models\PasswordChanges;
use illusion\Modules\Users\Models\ResetPasswords;
use illusion\Modules\Users\Models\Users;
use Phalcon\Mvc\Controller;
use Phalcon\Mvc\View;
 
class AuthController extends Controller
{
 
    /**
     * Acceso usuario
     */
    public function loginAction()
    {
 
        $this->moduleName = $this->dispatcher->getModuleName();
        $this->controllerName = $this->dispatcher->getControllerName();
        $this->actionName = $this->dispatcher->getActionName();
 
        $this->utils->addPageLevelAssets($this->moduleName, $this->controllerName, $this->actionName);
 
        $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
        $this->view->setVars(
            array(
                'pageTitle' => $this->t->_('Iniciar sesión'),
                'pageTitleSmall' => ''
            )
        );
 
 
        // Si el usuario vuelve al login con un 2FA pendiente, cancelarlo
        if ($this->session->has('pending_2fa')) {
            $this->session->remove('pending_2fa');
        }
 
        $form = new LoginForm();
 
        if (!$this->request->isPost()) {
            if ($this->auth->hasRememberMe()) {
                return $this->auth->loginWithRememberMe();
            }
        } else {
            if ($form->isValid($this->request->getPost()) == false) {
                foreach ($form->getMessages() as $message) {
                    $this->flash->error($message);
                }
            } else {
                $email    = $this->request->getPost('email', 'striptags');
                $password = $this->request->getPost('password', 'striptags');
                $remember = $this->request->getPost('remember');
 
                try {
                    $user = $this->auth->validateCredentials($email, $password);
 
                    $is2faEnabled = filter_var(
                        function_exists('env') ? env('APP_2FA_ENABLED', 'true') : 'true',
                        FILTER_VALIDATE_BOOLEAN
                    );
 
                    if ($is2faEnabled) {
                        $twoFactor = new TwoFactorService();
                        $codeId    = $twoFactor->generate($user);
                        $this->session->set('pending_2fa', [
                            'usersId'         => $user->id,
                            'twoFactorCodeId' => $codeId,
                            'email'           => $this->crypt->encrypt($email),
                            'password'        => $this->crypt->encrypt($password),
                            'remember'        => !empty($remember),
                        ]);
                        return $this->response->redirect('users/auth/verify2fa');
                    }
 
                    // 2FA deshabilitado: login directo
                    $this->auth->createSession($user, !empty($remember));
                    $this->session->remove('lock');
                    $this->session->remove('referer');
 
                    $url = 'dashboard';
                    if ($this->session->has('returnTo')) {
                        $returnTo = $this->session->get('returnTo');
                        if (!strpos($returnTo, 'users/login')) {
                            $url = $returnTo;
                        }
                        $this->session->remove('returnTo');
                    }
                    return $this->response->redirect($url);
                } catch (Exception $e) {
                    $this->flash->error($e->getMessage());
                }
            }
        }
 
        $this->view->setVar('loginForm', new LoginForm());
        $this->view->setVar('forgotForm', new ForgotPasswordForm());
    }
 
 
    /**
     * Activar cuenta de usuario despues del registro
     */
    public function confirmaccountAction($code)
    {
        // El $code por URL es plano; BD guarda sólo hash SHA-256.
        $user = Users::findFirst([
            'conditions' => 'code = :h:',
            'bind'       => ['h' => hash('sha256', (string)$code)],
        ]);
 
        if (!$user) {
            $this->flash->warning($this->t->_('El enlace ha caducado, puede solicitar una recuperación de contraseña.'));
            return $this->dispatcher->forward(array(
                'module' => 'users',
                'controller' => 'auth',
                'action' => 'login'
            ));
        }
 
        // if ($user->used == 'Y') {
        //     $this->flash->warning($this->t->_('El enlace ya ha sido utilizado, puede solicitar una recuperación de contraseña.'));
        //     return $this->dispatcher->forward(array(
        //         'module' => 'users',
        //         'controller' => 'auth',
        //         'action' => 'login'
        //     ));
        // }
 
        $dateLimit = \DateTime::createFromFormat('Y-m-d H:i:s', $user->codeCreatedAt);
        $dateLimit->modify('+24 hours');
        $dateNow = \DateTime::createFromFormat('Y-m-d H:i:s', date("Y-m-d H:i:s"));
        if ($dateNow > $dateLimit) {
            $this->flash->warning($this->t->_('El enlace ha caducado, puede solicitar una recuperación de contraseña.'));
            return $this->dispatcher->forward(array(
                'module' => 'users',
                'controller' => 'auth',
                'action' => 'login'
            ));
        }
 
        $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
        $form = new ConfirmaccountForm($user);
        if ($this->request->isPost()) {
            if ($form->isValid($this->request->getPost()) == false) {
                foreach ($form->getMessages() as $message) {
                    $this->flash->error($message);
                }
            } else {
                $user = Users::findFirstByHash($this->request->getPost('hash'));
                if (!$user) {
                    $this->flash->warning($this->t->_('El enlace ha caducado, puede solicitar una recuperación de contraseña.'));
                    return $this->dispatcher->forward(array(
                        'module' => 'users',
                        'controller' => 'auth',
                        'action' => 'login'
                    ));
                }
                $password = $this->request->getPost('passwordNew');
                $user->password = $this->security->hash($password);
                $passwordChange = new PasswordChanges();
                $passwordChange->usersId = $user->id;
                $passwordChange->ipAddress = $this->request->getClientAddress();
                $passwordChange->userAgent = $this->request->getUserAgent();
                $passwordChange->createdAt = date('Y-m-d H:i:s');
                $user->code = '';
                $user->codeUsedAt = date('Y-m-d H:i:s');
 
                $user->tmpPassword = $password;
                $user->update();
 
                $this->auth->authUserById($user->id);
                $this->flash->success($this->t->_('Contraseña guardada correctamente, ya puede acceder a %siteName%.', ['siteName' => $this->config->info->siteName]));
                return $this->response->redirect('');
            }
        }
        $this->view->form = $form;
        $this->view->code = $code;
    }
 
    /**
     * Formulario solicitar restablecer contraseña
     */
    public function rememberPasswordAction()
    {
 
        $this->moduleName = $this->dispatcher->getModuleName();
        $this->controllerName = $this->dispatcher->getControllerName();
        $this->actionName = $this->dispatcher->getActionName();
 
        $this->utils->addPageLevelAssets($this->moduleName, $this->controllerName, $this->actionName);
 
        $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
        $this->view->setVars(
            array(
                'pageTitle' => $this->t->_('Recuperar contraseña'),
                'pageTitleSmall' => ''
            )
        );
 
        $form = new ForgotPasswordForm();
 
        if ($this->request->isPost()) {
 
            if ($form->isValid($this->request->getPost()) == false) {
                foreach ($form->getMessages() as $message) {
                    $this->flash->error($this->t->_($message));
                }
            } else {
 
                $user = Users::findFirst("email = '" . $this->request->getPost('email') . "'");
 
                if (!$user) {
                    $this->flash->error($this->t->_('Esta acción no se puede realizar, datos incorrectos.'));
                } else {
                    if ($user->active == 'N' or $user->deleted == 'Y') {
                        $this->flash->error($this->t->_('Esta acción no se puede realizar, datos incorrectos.'));
                    } else {
                        $user->used = 'N';
                        $user->update();
 
                        $resetPassword = new ResetPasswords();
                        $resetPassword->usersId = $user->id;
                        $resetPassword->ipAddress = $this->request->getClientAddress();
                        $resetPassword->userAgent = $this->request->getUserAgent();
 
                        if ($resetPassword->save()) {
                            $this->flash->success($this->t->_('Le hemos enviado instrucciones al correo electrónico indicado.'));
                            return $this->response->redirect('users/auth/login');
                        } else {
                            foreach ($resetPassword->getMessages() as $message) {
                                $this->flash->error($this->t->_($message));
                            }
                        }
                    }
                }
            }
        }
        $this->view->forgotForm = $form;
    }
 
    /**
     * Formulario cambio contraseña
     */
    public function resetPasswordAction($code)
    {
 
        $this->moduleName = $this->dispatcher->getModuleName();
        $this->controllerName = $this->dispatcher->getControllerName();
        $this->actionName = $this->dispatcher->getActionName();
 
        $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
        $this->view->setVars(
            array(
                'pageTitle' => $this->t->_('Cambiar contraseña'),
                'pageTitleSmall' => ''
            )
        );
 
        // El $code que llega por URL es el plano. En BD guardamos sólo el
        // hash SHA-256 — comparamos hasheando lo recibido.
        $resetPassword = ResetPasswords::findFirst([
            'conditions' => 'code = :h:',
            'bind'       => ['h' => hash('sha256', (string)$code)],
        ]);
 
        if (!$resetPassword) {
            $this->flash->warning($this->t->_('El enlace ha caducado, deberá solicitar de nuevo un reinicio de contraseña.'));
            return $this->dispatcher->forward(array(
                'module' => 'users',
                'controller' => 'auth',
                'action' => 'login'
            ));
        }
 
        if ($resetPassword->reset != 'N') {
            $this->flash->warning($this->t->_('El enlace ya ha sido utilizado, deberá solicitar de nuevo un reinicio de contraseña.'));
            return $this->dispatcher->forward(array(
                'module' => 'users',
                'controller' => 'auth',
                'action' => 'login'
            ));
        }
 
        $dateLimit = \DateTime::createFromFormat('Y-m-d H:i:s', $resetPassword->createdAt);
        $dateLimit->modify('+24 hours');
        $dateNow = \DateTime::createFromFormat('Y-m-d H:i:s', date("Y-m-d H:i:s"));
        if ($dateNow > $dateLimit) {
            $this->flash->warning($this->t->_('El enlace ha caducado, deberá solicitar de nuevo un reinicio de contraseña.'));
            return $this->dispatcher->forward(array(
                'module' => 'users',
                'controller' => 'auth',
                'action' => 'login'
            ));
        }
 
        $tempPassword = preg_replace('/[^a-zA-Z0-9]/', '', base64_encode(openssl_random_pseudo_bytes(12)));
        $resetPassword->User->tmpPassword = $tempPassword;
        $resetPassword->User->password = $this->security->hash($tempPassword);
        $resetPassword->User->save();
 
        $passwordForm = new PasswordForm(null, array(
            'edit' => true
        ));
 
        $this->view->form = $passwordForm;
 
        if ($this->request->isPost()) {
 
            if (!$passwordForm->isValid($this->request->getPost())) {
                foreach ($passwordForm->getMessages() as $message) {
                    $this->flash->error($message);
                }
                return $this->response->redirect($this->request->getHTTPReferer());
            } else {
 
                $password = $this->request->getPost('passwordNew', 'striptags');
                $confirmPassword = $this->request->getPost('confirmPassword', 'striptags');
                if (strlen($password) > 0 && strlen($confirmPassword) > 0) {
 
                    $user2 = $resetPassword->User;
 
                    $user2->password = $this->security->hash($password);
                    $passwordChange = new PasswordChanges();
                    $passwordChange->usersId = $user2->id;
                    $passwordChange->ipAddress = $this->request->getClientAddress();
                    $passwordChange->userAgent = $this->request->getUserAgent();
                    $passwordChange->createdAt = date('Y-m-d H:i:s');
 
                    $passwordChange->save();
                    $user2->save();
 
                    $this->flash->success($this->t->_('Contraseña establecida correctamente.'));
 
                    $this->session->set('credentials', array(
                        'email' => $this->crypt->encrypt($user2->email, $this->config->application->cryptSalt),
                        'password' => $this->crypt->encrypt($password, $this->config->application->cryptSalt)
                    ));
                    return $this->response->redirect('users/auth/login');
                }
            }
        }
 
        $this->view->code = $code;
 
    }
 
    /**
     * Verificación del código OTP de segundo factor.
     */
    public function verify2faAction()
    {
        $pending = $this->session->get('pending_2fa');
 
        if (!$pending || !isset($pending['usersId'], $pending['twoFactorCodeId'])) {
            return $this->response->redirect('users/auth/login');
        }
 
        $this->view->setRenderLevel(View::LEVEL_ACTION_VIEW);
        $this->view->setVars([
            'pageTitle'      => $this->t->_('Verificación en dos pasos'),
            'pageTitleSmall' => '',
        ]);
 
        if ($this->request->isPost()) {
            $inputCode = trim((string)$this->request->getPost('otp_code', 'striptags'));
 
            $twoFactor = new TwoFactorService();
            $result    = $twoFactor->verify(
                (int)$pending['twoFactorCodeId'],
                (int)$pending['usersId'],
                $inputCode
            );
 
            switch ($result) {
                case 'ok':
                    $user = Users::findFirstById((int)$pending['usersId']);
                    if (!$user) {
                        $this->session->remove('pending_2fa');
                        return $this->response->redirect('users/auth/login');
                    }
                    $this->auth->createSession($user, (bool)($pending['remember'] ?? false));
                    $this->session->remove('pending_2fa');
                    $this->session->remove('lock');
                    $this->session->remove('referer');
 
                    $url = 'dashboard';
                    if ($this->session->has('returnTo')) {
                        $returnTo = $this->session->get('returnTo');
                        if (!strpos($returnTo, 'users/login')) {
                            $url = $returnTo;
                        }
                        $this->session->remove('returnTo');
                    }
                    return $this->response->redirect($url);
 
                case 'exhausted':
                case 'invalid':
                    $this->session->remove('pending_2fa');
                    $this->flash->error($this->t->_('Código inválido o expirado. Inicia sesión de nuevo.'));
                    return $this->response->redirect('users/auth/login');
 
                case 'wrong':
                default:
                    $this->flash->error($this->t->_('Código incorrecto. Inténtalo de nuevo.'));
                    break;
            }
        }
    }
 
}
#22illusion\Modules\Users\Controllers\AuthController->loginAction()
#23Phalcon\Dispatcher\AbstractDispatcher->callActionMethod(Object(illusion\Modules\Users\Controllers\AuthController), loginAction, Array())
#24Phalcon\Dispatcher\AbstractDispatcher->dispatch()
#25Phalcon\Mvc\Application->handle(/users/auth/login)
/home/laberitillusions/public_html/public/index.php (102)
<?php
 
// Cargamos el helper env() antes de cualquier cosa (no depende de nada)
require_once dirname(__DIR__) . '/apps/config/env_variable_loader.php';
 
ini_set("session.cookie_lifetime", "14400");
ini_set("session.gc_maxlifetime", "14000");
 
// Endurecimiento de la cookie de sesión (aplicar ANTES de session_start).
// JS no puede leer la cookie:
ini_set('session.cookie_httponly', '1');
// Bloquea envío cross-site en POST/navegación top-level sospechosa (protección CSRF básica):
ini_set('session.cookie_samesite', 'Lax');
// Rechaza session_id no emitido por PHP (mitiga session fixation a bajo nivel):
ini_set('session.use_strict_mode', '1');
// Secure solo tiene sentido sobre HTTPS; en local WAMP romperíamos el login.
if ((!defined('APPLICATION_ENV') || getenv('APPLICATION_ENV') !== 'local') && !empty($_SERVER['HTTPS'])) {
    ini_set('session.cookie_secure', '1');
}
 
use Phalcon\Mvc\Application;
 
date_default_timezone_set('Europe/Madrid');
setlocale(LC_ALL, array("es_ES"));
setlocale(LC_MONETARY, 'es_ES');
 
if (!defined('APPLICATION_ENV')) {
    define('APPLICATION_ENV', 'local');
}
 
 
if (!defined('BASE_DIR')) {
    define('BASE_DIR', dirname(__DIR__));
}
 
// Composer autoloader necesario para que class_exists(Dotenv\Dotenv) funcione
// (loader.php lo cargará de nuevo pero require_once lo omite si ya está cargado)
if (is_file(BASE_DIR . '/vendor/autoload.php')) {
    require_once BASE_DIR . '/vendor/autoload.php';
}
 
// Dotenv: carga .env.{env} o .env si el paquete vlucas/phpdotenv está instalado.
// En local, APPLICATION_ENV puede no estar definido aún — fallback a 'local' para
// que .env.local se cargue automáticamente sin configurar Apache.
if (class_exists(\Dotenv\Dotenv::class)) {
    $appEnv = $_ENV['APPLICATION_ENV'] ?? $_SERVER['APPLICATION_ENV'] ?? getenv('APPLICATION_ENV');
    if (!is_string($appEnv) || $appEnv === '') {
        $appEnv = 'local';
    }
    foreach (['.env.' . $appEnv, '.env'] as $_envCandidate) {
        if (is_file(BASE_DIR . '/' . $_envCandidate)) {
            \Dotenv\Dotenv::createImmutable(BASE_DIR, $_envCandidate)->safeLoad();
            break;
        }
    }
    unset($appEnv, $_envCandidate);
}
 
// Fail-secure: solo 'local' expone errores por pantalla. Cualquier otro env (pre/pro/…) los oculta y loguea.
if (APPLICATION_ENV === 'local') {
    error_reporting(E_ALL);
    ini_set('display_errors', '1');
    ini_set('display_startup_errors', '1');
} else {
    error_reporting(E_ALL & ~E_DEPRECATED & ~E_NOTICE & ~E_STRICT);
    ini_set('display_errors', '0');
    ini_set('display_startup_errors', '0');
    ini_set('log_errors', '1');
    ini_set('error_log', BASE_DIR . '/apps/logs/php_errors.log');
}
 
include BASE_DIR . '/apps/config/constants.php';
 
include BASE_DIR . '/apps/config/c_modules.php';
 
$config = include APPS_DIR . '/config/environment/' . APPLICATION_ENV . '/base-config.php';
$ini_file = BASE_DIR . '/private/config/environment/' . APPLICATION_ENV . '/base-config.ini';
 
$config2 = new \Phalcon\Config\Adapter\Ini($ini_file);
 
$config->merge($config2);
 
include APPS_DIR . '/config/loader.php';
include APPS_DIR . '/config/services.php';
 
$application = new Application();
$application->setDI($di);
 
require APPS_DIR . '/config/modules.php';
 
//$baseUri = str_replace('/public/index.php', '', $_SERVER['PHP_SELF']);
//$uri = str_replace($baseUri, '', $_SERVER['REQUEST_URI']);
//echo $application->handle($uri)->getContent();
 
//$path = str_replace($_SERVER["DOCUMENT_ROOT"], '', str_replace("\\", "/", BASE_DIR));
//$uri = str_replace($path, '', $_SERVER['REQUEST_URI']);
//echo $application->handle($uri)->getContent();
 
//echo $application->handle($_SERVER['REQUEST_URI'])->getContent();
 
$request = $di->getShared('request');
echo $application->handle($request->getURI())->getContent();
KeyValue
_url/users/auth/login
KeyValue
USERlaberitillusions
HOME/home/laberitillusions
SCRIPT_NAME/public/index.php
REQUEST_URI/users/auth/login
QUERY_STRING_url=/users/auth/login
REQUEST_METHODGET
SERVER_PROTOCOLHTTP/2.0
GATEWAY_INTERFACECGI/1.1
REDIRECT_QUERY_STRING_url=/users/auth/login
REDIRECT_URL/public/users/auth/login
REMOTE_PORT53429
SCRIPT_FILENAME/home/laberitillusions/public_html/public/index.php
SERVER_ADMINwebmaster@laberit.illusionstudio.es
CONTEXT_DOCUMENT_ROOT/home/laberitillusions/public_html
CONTEXT_PREFIX
REQUEST_SCHEMEhttps
DOCUMENT_ROOT/home/laberitillusions/public_html
REMOTE_ADDR216.73.216.55
SERVER_PORT443
SERVER_ADDR51.178.37.224
SERVER_NAMElaberit.illusionstudio.es
SERVER_SOFTWAREApache
SERVER_SIGNATURE
PATH/usr/local/jdk/bin:/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/usr/X11R6/bin:/usr/local/bin:/usr/X11R6/bin:/root/bin:/opt/bin
HTTP_X_HTTPS1
HTTP_HOSTlaberit.illusionstudio.es
HTTP_REFERERhttps://laberit.illusionstudio.es/sitemap.xml
HTTP_ACCEPT_ENCODINGgzip, br, zstd, deflate
HTTP_COOKIEPHPSESSID=33c34a796b4f00e153afe3574b9de47e
HTTP_USER_AGENTMozilla/5.0 AppleWebKit/537.36 (KHTML, like Gecko; compatible; ClaudeBot/1.0; +claudebot@anthropic.com)
HTTP_ACCEPT*/*
proxy-nokeepalive1
H2_STREAM_TAG3060560-62-7
H2_STREAM_ID7
H2_PUSHED_ON
H2_PUSHED
H2_PUSHoff
H2PUSHoff
HTTP2on
SSL_TLS_SNIlaberit.illusionstudio.es
HTTPSon
SCRIPT_URIhttps://laberit.illusionstudio.es/users/auth/login
SCRIPT_URL/users/auth/login
UNIQUE_IDah4VYa6XTyf4j2sWSlEd5gABEQQ
REDIRECT_STATUS200
REDIRECT_H2_STREAM_TAG3060560-62-7
REDIRECT_H2_STREAM_ID7
REDIRECT_H2_PUSHED_ON
REDIRECT_H2_PUSHED
REDIRECT_H2_PUSHoff
REDIRECT_H2PUSHoff
REDIRECT_HTTP2on
REDIRECT_SSL_TLS_SNIlaberit.illusionstudio.es
REDIRECT_HTTPSon
REDIRECT_SCRIPT_URIhttps://laberit.illusionstudio.es/users/auth/login
REDIRECT_SCRIPT_URL/users/auth/login
REDIRECT_UNIQUE_IDah4VYa6XTyf4j2sWSlEd5gABEQQ
REDIRECT_REDIRECT_STATUS200
REDIRECT_REDIRECT_H2_STREAM_TAG3060560-62-7
REDIRECT_REDIRECT_H2_STREAM_ID7
REDIRECT_REDIRECT_H2_PUSHED_ON
REDIRECT_REDIRECT_H2_PUSHED
REDIRECT_REDIRECT_H2_PUSHoff
REDIRECT_REDIRECT_H2PUSHoff
REDIRECT_REDIRECT_HTTP2on
REDIRECT_REDIRECT_SSL_TLS_SNIlaberit.illusionstudio.es
REDIRECT_REDIRECT_HTTPSon
REDIRECT_REDIRECT_SCRIPT_URIhttps://laberit.illusionstudio.es/users/auth/login
REDIRECT_REDIRECT_SCRIPT_URL/users/auth/login
REDIRECT_REDIRECT_UNIQUE_IDah4VYa6XTyf4j2sWSlEd5gABEQQ
FCGI_ROLERESPONDER
PHP_SELF/public/index.php
REQUEST_TIME_FLOAT1780356449.8937
REQUEST_TIME1780356449
argvArray([0] => _url=/users/auth/login)
argc1
#Path
0/home/laberitillusions/public_html/public/index.php
1/home/laberitillusions/public_html/apps/config/env_variable_loader.php
2/home/laberitillusions/public_html/vendor/autoload.php
3/home/laberitillusions/public_html/vendor/composer/autoload_real.php
4/home/laberitillusions/public_html/vendor/composer/platform_check.php
5/home/laberitillusions/public_html/vendor/composer/ClassLoader.php
6/home/laberitillusions/public_html/vendor/composer/autoload_static.php
7/home/laberitillusions/public_html/vendor/ralouphie/getallheaders/src/getallheaders.php
8/home/laberitillusions/public_html/vendor/symfony/polyfill-intl-normalizer/bootstrap.php
9/home/laberitillusions/public_html/vendor/symfony/polyfill-intl-normalizer/bootstrap80.php
10/home/laberitillusions/public_html/vendor/guzzlehttp/promises/src/functions_include.php
11/home/laberitillusions/public_html/vendor/guzzlehttp/promises/src/functions.php
12/home/laberitillusions/public_html/vendor/guzzlehttp/psr7/src/functions_include.php
13/home/laberitillusions/public_html/vendor/guzzlehttp/psr7/src/functions.php
14/home/laberitillusions/public_html/vendor/symfony/polyfill-intl-idn/bootstrap.php
15/home/laberitillusions/public_html/vendor/guzzlehttp/guzzle/src/functions_include.php
16/home/laberitillusions/public_html/vendor/guzzlehttp/guzzle/src/functions.php
17/home/laberitillusions/public_html/apps/config/constants.php
18/home/laberitillusions/public_html/apps/config/c_modules.php
19/home/laberitillusions/public_html/apps/config/environment/local/base-config.php
20/home/laberitillusions/public_html/apps/config/loader.php
21/home/laberitillusions/public_html/apps/config/services.php
22/home/laberitillusions/public_html/apps/modules/core/Module.php
23/home/laberitillusions/public_html/apps/common/plugins/SecurityPlugin.php
24/home/laberitillusions/public_html/apps/common/plugins/SecurityHeadersPlugin.php
25/home/laberitillusions/public_html/apps/common/plugins/NotFoundPlugin.php
26/home/laberitillusions/public_html/apps/common/plugins/ForwardPlugin.php
27/home/laberitillusions/public_html/apps/common/libraries/Auth/Auth.php
28/home/laberitillusions/public_html/apps/modules/users/Module.php
29/home/laberitillusions/public_html/apps/modules/app/Module.php
30/home/laberitillusions/public_html/apps/config/modules.php
31/home/laberitillusions/public_html/apps/config/routes.php
32/home/laberitillusions/public_html/apps/modules/core/routes/CoreRoutes.php
33/home/laberitillusions/public_html/apps/modules/users/routes/UsersRoutes.php
34/home/laberitillusions/public_html/apps/modules/app/routes/AppRoutes.php
35/home/laberitillusions/public_html/apps/common/libraries/Acl/Acl.php
36/home/laberitillusions/public_html/apps/modules/users/controllers/AuthController.php
37/home/laberitillusions/public_html/apps/common/libraries/Utils/Utils.php
38/home/laberitillusions/public_html/apps/common/models/Languages.php
39/home/laberitillusions/public_html/apps/common/models/AbstractModel.php
40/home/laberitillusions/public_html/apps/common/traits/ModelControl.php
Memory
Usage2097152

Fatal error: Uncaught PDOException: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: NO) in /home/laberitillusions/public_html/apps/config/services.php:91 Stack trace: #0 [internal function]: PDO->__construct('mysql:charset=u...', 'root', '', Array) #1 [internal function]: Phalcon\Db\Adapter\Pdo\AbstractPdo->connect(Array) #2 /home/laberitillusions/public_html/apps/config/services.php(91): Phalcon\Db\Adapter\Pdo\AbstractPdo->__construct(Array) #3 [internal function]: Closure->illusion\{closure}() #4 [internal function]: Phalcon\Di\Service->resolve(NULL, Object(Phalcon\Di\FactoryDefault)) #5 [internal function]: Phalcon\Di\Di->get('db', NULL) #6 [internal function]: Phalcon\Di\Di->getShared('db') #7 [internal function]: Phalcon\Mvc\Model\Manager->getConnection(Object(illusion\Common\Models\Languages), Array) #8 [internal function]: Phalcon\Mvc\Model\Manager->getReadConnection(Object(illusion\Common\Models\Languages)) #9 [internal function]: Phalcon\Mvc\Model->getReadConnection() #10 [internal function]: Phalcon\Mvc\Model\MetaData\Strategy\Introspection->getMetaData(Object(illusion\Common\Models\Languages), Object(Phalcon\Di\FactoryDefault)) #11 [internal function]: Phalcon\Mvc\Model\MetaData->initializeMetaData(Object(illusion\Common\Models\Languages), 'illusion\\common...') #12 [internal function]: Phalcon\Mvc\Model\MetaData->getMetaDataUniqueKey(Object(illusion\Common\Models\Languages)) #13 [internal function]: Phalcon\Mvc\Model\MetaData->readMetaDataIndex(Object(illusion\Common\Models\Languages), 4) #14 [internal function]: Phalcon\Mvc\Model\MetaData->getDataTypes(Object(illusion\Common\Models\Languages)) #15 [internal function]: Phalcon\Mvc\Model::invokeFinder('findFirstByLang', Array) #16 /home/laberitillusions/public_html/apps/config/services.php(208): Phalcon\Mvc\Model::__callStatic('findFirstByLang', Array) #17 [internal function]: Closure->illusion\{closure}() #18 [internal function]: Phalcon\Di\Service->resolve(NULL, Object(Phalcon\Di\FactoryDefault)) #19 [internal function]: Phalcon\Di\Di->get('t', NULL) #20 [internal function]: Phalcon\Di\Di->getShared('t') #21 /home/laberitillusions/public_html/apps/modules/users/controllers/AuthController.php(36): Phalcon\Di\Injectable->__get('t') #22 [internal function]: illusion\Modules\Users\Controllers\AuthController->loginAction() #23 [internal function]: Phalcon\Dispatcher\AbstractDispatcher->callActionMethod(Object(illusion\Modules\Users\Controllers\AuthController), 'loginAction', Array) #24 [internal function]: Phalcon\Dispatcher\AbstractDispatcher->dispatch() #25 /home/laberitillusions/public_html/public/index.php(102): Phalcon\Mvc\Application->handle('/users/auth/log...') #26 {main} thrown in /home/laberitillusions/public_html/apps/config/services.php on line 91