vendor/pimcore/pimcore/bundles/AdminBundle/Controller/Admin/LoginController.php line 119

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Enterprise License (PEL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  * @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  12.  * @license    http://www.pimcore.org/license     GPLv3 and PEL
  13.  */
  14. namespace Pimcore\Bundle\AdminBundle\Controller\Admin;
  15. use Pimcore\Bundle\AdminBundle\Controller\AdminController;
  16. use Pimcore\Bundle\AdminBundle\Controller\BruteforceProtectedControllerInterface;
  17. use Pimcore\Bundle\AdminBundle\EventListener\CsrfProtectionListener;
  18. use Pimcore\Bundle\AdminBundle\Security\BruteforceProtectionHandler;
  19. use Pimcore\Config;
  20. use Pimcore\Controller\Configuration\TemplatePhp;
  21. use Pimcore\Controller\EventedControllerInterface;
  22. use Pimcore\Event\Admin\Login\LostPasswordEvent;
  23. use Pimcore\Event\AdminEvents;
  24. use Pimcore\Http\ResponseHelper;
  25. use Pimcore\Logger;
  26. use Pimcore\Model\User;
  27. use Pimcore\Templating\Model\ViewModel;
  28. use Pimcore\Tool;
  29. use Pimcore\Tool\Authentication;
  30. use Symfony\Component\HttpFoundation\RedirectResponse;
  31. use Symfony\Component\HttpFoundation\Request;
  32. use Symfony\Component\HttpFoundation\Response;
  33. use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
  34. use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  35. use Symfony\Component\Routing\Annotation\Route;
  36. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  37. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  38. use Symfony\Component\Security\Core\Security;
  39. use Symfony\Component\Security\Core\User\UserInterface;
  40. class LoginController extends AdminController implements BruteforceProtectedControllerInterfaceEventedControllerInterface
  41. {
  42.     /**
  43.      * @var ResponseHelper
  44.      */
  45.     protected $reponseHelper;
  46.     public function __construct(ResponseHelper $responseHelper)
  47.     {
  48.         $this->reponseHelper $responseHelper;
  49.     }
  50.     public function onKernelController(FilterControllerEvent $event)
  51.     {
  52.         // use browser language for login page if possible
  53.         $locale 'en';
  54.         $availableLocales Tool\Admin::getLanguages();
  55.         foreach ($event->getRequest()->getLanguages() as $userLocale) {
  56.             if (in_array($userLocale$availableLocales)) {
  57.                 $locale $userLocale;
  58.                 break;
  59.             }
  60.         }
  61.         $this->get('translator')->setLocale($locale);
  62.     }
  63.     public function onKernelResponse(FilterResponseEvent $event)
  64.     {
  65.         $response $event->getResponse();
  66.         $response->headers->set('X-Frame-Options''deny'true);
  67.         $this->reponseHelper->disableCache($responsetrue);
  68.     }
  69.     /**
  70.      * @Route("/login", name="pimcore_admin_login")
  71.      * @Route("/login/", name="pimcore_admin_login_fallback")
  72.      *
  73.      * @TemplatePhp()
  74.      */
  75.     public function loginAction(Request $requestCsrfProtectionListener $csrfProtectionListenerConfig $config)
  76.     {
  77.         if ($request->get('_route') === 'pimcore_admin_login_fallback') {
  78.             return $this->redirectToRoute('pimcore_admin_login'$request->query->all(), Response::HTTP_MOVED_PERMANENTLY);
  79.         }
  80.         $csrfProtectionListener->regenerateCsrfToken();
  81.         $user $this->getAdminUser();
  82.         if ($user instanceof UserInterface) {
  83.             return $this->redirectToRoute('pimcore_admin_index');
  84.         }
  85.         $view $this->buildLoginPageViewModel($config);
  86.         $session_gc_maxlifetime ini_get('session.gc_maxlifetime');
  87.         if (empty($session_gc_maxlifetime)) {
  88.             $session_gc_maxlifetime 120;
  89.         }
  90.         $view->csrfTokenRefreshInterval = ((int)$session_gc_maxlifetime 60) * 1000;
  91.         if ($request->get('auth_failed')) {
  92.             $view->error 'error_auth_failed';
  93.         }
  94.         if ($request->get('session_expired')) {
  95.             $view->error 'error_session_expired';
  96.         }
  97.         return $view;
  98.     }
  99.     /**
  100.      * @Route("/login/csrf-token", name="pimcore_admin_login_csrf_token")
  101.      */
  102.     public function csrfTokenAction(Request $requestCsrfProtectionListener $csrfProtectionListener)
  103.     {
  104.         $csrfProtectionListener->regenerateCsrfToken();
  105.         return $this->json([
  106.            'csrfToken' => $csrfProtectionListener->getCsrfToken()
  107.         ]);
  108.     }
  109.     /**
  110.      * @Route("/logout", name="pimcore_admin_logout")
  111.      */
  112.     public function logoutAction()
  113.     {
  114.         // this route will never be matched, but will be handled by the logout handler
  115.     }
  116.     /**
  117.      * Dummy route used to check authentication
  118.      *
  119.      * @Route("/login/login", name="pimcore_admin_login_check")
  120.      *
  121.      * @see AdminAuthenticator for the security implementation
  122.      */
  123.     public function loginCheckAction()
  124.     {
  125.         // just in case the authenticator didn't redirect
  126.         return new RedirectResponse($this->generateUrl('pimcore_admin_login'));
  127.     }
  128.     /**
  129.      * @Route("/login/lostpassword", name="pimcore_admin_login_lostpassword")
  130.      * @TemplatePhp()
  131.      */
  132.     public function lostpasswordAction(Request $requestBruteforceProtectionHandler $bruteforceProtectionHandlerCsrfProtectionListener $csrfProtectionListenerConfig $config)
  133.     {
  134.         $view $this->buildLoginPageViewModel($config);
  135.         $error null;
  136.         if ($request->getMethod() === 'POST' && $username $request->get('username')) {
  137.             $user User::getByName($username);
  138.             if ($user instanceof User) {
  139.                 if (!$user->isActive()) {
  140.                     $error 'user inactive';
  141.                 }
  142.                 if (!$user->getEmail()) {
  143.                     $error 'user has no email address';
  144.                 }
  145.                 if (!$user->getPassword()) {
  146.                     $error 'user has no password';
  147.                 }
  148.             } else {
  149.                 $error 'user unknown';
  150.             }
  151.             if (!$error && $user instanceof User) {
  152.                 $token Authentication::generateToken($user->getName());
  153.                 $loginUrl $this->generateUrl('pimcore_admin_login_check', [
  154.                     'token' => $token,
  155.                     'reset' => 'true'
  156.                 ], UrlGeneratorInterface::ABSOLUTE_URL);
  157.                 try {
  158.                     $event = new LostPasswordEvent($user$loginUrl);
  159.                     $this->get('event_dispatcher')->dispatch(AdminEvents::LOGIN_LOSTPASSWORD$event);
  160.                     // only send mail if it wasn't prevented in event
  161.                     if ($event->getSendMail()) {
  162.                         $mail Tool::getMail([$user->getEmail()], 'Pimcore lost password service');
  163.                         $mail->setIgnoreDebugMode(true);
  164.                         $mail->setBodyText("Login to pimcore and change your password using the following link. This temporary login link will expire in 24 hours: \r\n\r\n" $loginUrl);
  165.                         $mail->send();
  166.                     }
  167.                     // directly return event response
  168.                     if ($event->hasResponse()) {
  169.                         return $event->getResponse();
  170.                     }
  171.                 } catch (\Exception $e) {
  172.                     $error 'could not send email';
  173.                 }
  174.             }
  175.             if ($error) {
  176.                 Logger::error('Lost password service: ' $error);
  177.                 $bruteforceProtectionHandler->addEntry($request->get('username'), $request);
  178.             }
  179.         }
  180.         $csrfProtectionListener->regenerateCsrfToken();
  181.         return $view;
  182.     }
  183.     /**
  184.      * @Route("/login/deeplink", name="pimcore_admin_login_deeplink")
  185.      * @TemplatePhp()
  186.      */
  187.     public function deeplinkAction(Request $request)
  188.     {
  189.         // check for deeplink
  190.         $queryString $_SERVER['QUERY_STRING'];
  191.         if (preg_match('/(document|asset|object)_([0-9]+)_([a-z]+)/'$queryString$deeplink)) {
  192.             $deeplink $deeplink[0];
  193.             $perspective strip_tags($request->get('perspective'));
  194.             if (strpos($queryString'token')) {
  195.                 $url $this->generateUrl('pimcore_admin_login', [
  196.                     'deeplink' => $deeplink,
  197.                     'perspective' => $perspective
  198.                 ]);
  199.                 $url .= '&' $queryString;
  200.                 return $this->redirect($url);
  201.             } elseif ($queryString) {
  202.                 return new ViewModel([
  203.                     'tab' => $deeplink,
  204.                     'perspective' => $perspective
  205.                 ]);
  206.             }
  207.         }
  208.     }
  209.     /**
  210.      * @return ViewModel
  211.      */
  212.     protected function buildLoginPageViewModel(Config $config)
  213.     {
  214.         $bundleManager $this->get('pimcore.extension.bundle_manager');
  215.         $view = new ViewModel([
  216.             'config' => $config,
  217.             'pluginCssPaths' => $bundleManager->getCssPaths()
  218.         ]);
  219.         return $view;
  220.     }
  221.     /**
  222.      * @Route("/login/2fa", name="pimcore_admin_2fa")
  223.      * @TemplatePhp()
  224.      */
  225.     public function twoFactorAuthenticationAction(Request $requestBruteforceProtectionHandler $bruteforceProtectionHandlerConfig $config)
  226.     {
  227.         $view $this->buildLoginPageViewModel($config);
  228.         if ($request->hasSession()) {
  229.             // we have to call the check here manually, because BruteforceProtectionListener uses the 'username' from the request
  230.             $bruteforceProtectionHandler->checkProtection($this->getAdminUser()->getName(), $request);
  231.             $session $request->getSession();
  232.             $authException $session->get(Security::AUTHENTICATION_ERROR);
  233.             if ($authException instanceof AuthenticationException) {
  234.                 $session->remove(Security::AUTHENTICATION_ERROR);
  235.                 $view->error $authException->getMessage();
  236.                 $bruteforceProtectionHandler->addEntry($this->getAdminUser()->getName(), $request);
  237.             }
  238.         } else {
  239.             $view->error 'No session available, it either timed out or cookies are not enabled.';
  240.         }
  241.         return $view;
  242.     }
  243.     /**
  244.      * @Route("/login/2fa-verify", name="pimcore_admin_2fa-verify")
  245.      *
  246.      * @param Request $request
  247.      */
  248.     public function twoFactorAuthenticationVerifyAction(Request $request)
  249.     {
  250.     }
  251. }