vendor/pimcore/pimcore/bundles/AdminBundle/Controller/Admin/IndexController.php line 132

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 Commercial License (PCL)
  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 PCL
  13.  */
  14. namespace Pimcore\Bundle\AdminBundle\Controller\Admin;
  15. use Doctrine\DBAL\Connection;
  16. use Exception;
  17. use Pimcore\Analytics\Google\Config\SiteConfigProvider;
  18. use Pimcore\Bundle\AdminBundle\Controller\AdminController;
  19. use Pimcore\Bundle\AdminBundle\HttpFoundation\JsonResponse;
  20. use Pimcore\Bundle\AdminBundle\Security\CsrfProtectionHandler;
  21. use Pimcore\Config;
  22. use Pimcore\Controller\KernelResponseEventInterface;
  23. use Pimcore\Event\Admin\IndexActionSettingsEvent;
  24. use Pimcore\Event\AdminEvents;
  25. use Pimcore\Maintenance\Executor;
  26. use Pimcore\Maintenance\ExecutorInterface;
  27. use Pimcore\Model\Document\DocType;
  28. use Pimcore\Model\Element\Service;
  29. use Pimcore\Model\Staticroute;
  30. use Pimcore\Model\User;
  31. use Pimcore\Tool;
  32. use Pimcore\Tool\Admin;
  33. use Pimcore\Tool\Session;
  34. use Pimcore\Version;
  35. use Symfony\Component\HttpFoundation\Request;
  36. use Symfony\Component\HttpFoundation\Response;
  37. use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
  38. use Symfony\Component\HttpKernel\Event\ResponseEvent;
  39. use Symfony\Component\HttpKernel\KernelInterface;
  40. use Symfony\Component\Routing\Annotation\Route;
  41. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  42. use Symfony\Contracts\EventDispatcher\EventDispatcherInterface;
  43. /**
  44.  * @internal
  45.  */
  46. class IndexController extends AdminController implements KernelResponseEventInterface
  47. {
  48.     /**
  49.      * @var EventDispatcherInterface
  50.      */
  51.     private $eventDispatcher;
  52.     /**
  53.      * @param EventDispatcherInterface $eventDispatcher
  54.      */
  55.     public function __construct(EventDispatcherInterface $eventDispatcher)
  56.     {
  57.         $this->eventDispatcher $eventDispatcher;
  58.     }
  59.     /**
  60.      * @Route("/", name="pimcore_admin_index", methods={"GET"})
  61.      *
  62.      * @param Request $request
  63.      * @param SiteConfigProvider $siteConfigProvider
  64.      * @param KernelInterface $kernel
  65.      * @param Executor $maintenanceExecutor
  66.      * @param CsrfProtectionHandler $csrfProtection
  67.      * @param Config $config
  68.      *
  69.      * @return Response
  70.      *
  71.      * @throws \Exception
  72.      */
  73.     public function indexAction(
  74.         Request $request,
  75.         SiteConfigProvider $siteConfigProvider,
  76.         KernelInterface $kernel,
  77.         Executor $maintenanceExecutor,
  78.         CsrfProtectionHandler $csrfProtection,
  79.         Config $config
  80.     ) {
  81.         $user $this->getAdminUser();
  82.         $perspectiveConfig = new \Pimcore\Perspective\Config();
  83.         $templateParams = [
  84.             'config' => $config,
  85.             'perspectiveConfig' => $perspectiveConfig,
  86.         ];
  87.         $this
  88.             ->addRuntimePerspective($templateParams$user)
  89.             ->addPluginAssets($templateParams);
  90.         $this->buildPimcoreSettings($request$templateParams$user$kernel$maintenanceExecutor$csrfProtection$siteConfigProvider);
  91.         if ($user->getTwoFactorAuthentication('required') && !$user->getTwoFactorAuthentication('enabled')) {
  92.             // only one login is allowed to setup 2FA by the user himself
  93.             $user->setTwoFactorAuthentication('enabled'true);
  94.             // disable the 2FA prompt for the current session
  95.             Tool\Session::useSession(function (AttributeBagInterface $adminSession) {
  96.                 $adminSession->set('2fa_required'false);
  97.             });
  98.             $user->save();
  99.             $templateParams['settings']['twoFactorSetupRequired'] = true;
  100.         }
  101.         // allow to alter settings via an event
  102.         $settingsEvent = new IndexActionSettingsEvent($templateParams['settings'] ?? []);
  103.         $this->eventDispatcher->dispatch($settingsEventAdminEvents::INDEX_ACTION_SETTINGS);
  104.         $templateParams['settings'] = $settingsEvent->getSettings();
  105.         return $this->render('@PimcoreAdmin/Admin/Index/index.html.twig'$templateParams);
  106.     }
  107.     /**
  108.      * @Route("/index/statistics", name="pimcore_admin_index_statistics", methods={"GET"})
  109.      *
  110.      * @param Request $request
  111.      * @param Connection $db
  112.      * @param KernelInterface $kernel
  113.      *
  114.      * @return JsonResponse
  115.      *
  116.      * @throws \Exception
  117.      */
  118.     public function statisticsAction(Request $requestConnection $dbKernelInterface $kernel)
  119.     {
  120.         // DB
  121.         try {
  122.             $tables $db->fetchAllAssociative('SELECT TABLE_NAME as name,TABLE_ROWS as `rows` from information_schema.TABLES
  123.                 WHERE TABLE_ROWS IS NOT NULL AND TABLE_SCHEMA = ?', [$db->getDatabase()]);
  124.         } catch (\Exception $e) {
  125.             $tables = [];
  126.         }
  127.         try {
  128.             $mysqlVersion $db->fetchOne('SELECT VERSION()');
  129.         } catch (\Exception $e) {
  130.             $mysqlVersion null;
  131.         }
  132.         try {
  133.             $data = [
  134.                 'instanceId' => $this->getInstanceId(),
  135.                 'pimcore_major_version' => 10,
  136.                 'pimcore_version' => Version::getVersion(),
  137.                 'pimcore_hash' => Version::getRevision(),
  138.                 'php_version' => PHP_VERSION,
  139.                 'mysql_version' => $mysqlVersion,
  140.                 'bundles' => array_keys($kernel->getBundles()),
  141.                 'tables' => $tables,
  142.             ];
  143.         } catch (\Exception $e) {
  144.             $data = [];
  145.         }
  146.         return $this->adminJson($data);
  147.     }
  148.     /**
  149.      * @param array $templateParams
  150.      * @param User $user
  151.      *
  152.      * @return $this
  153.      */
  154.     protected function addRuntimePerspective(array &$templateParamsUser $user)
  155.     {
  156.         $runtimePerspective \Pimcore\Perspective\Config::getRuntimePerspective($user);
  157.         $templateParams['runtimePerspective'] = $runtimePerspective;
  158.         return $this;
  159.     }
  160.     /**
  161.      * @param array $templateParams
  162.      *
  163.      * @return $this
  164.      */
  165.     protected function addPluginAssets(array &$templateParams)
  166.     {
  167.         $templateParams['pluginJsPaths'] = $this->getBundleManager()->getJsPaths();
  168.         $templateParams['pluginCssPaths'] = $this->getBundleManager()->getCssPaths();
  169.         return $this;
  170.     }
  171.     /**
  172.      * @param Request $request
  173.      * @param array $templateParams
  174.      * @param User $user
  175.      * @param KernelInterface $kernel
  176.      * @param ExecutorInterface $maintenanceExecutor
  177.      * @param CsrfProtectionHandler $csrfProtection
  178.      * @param SiteConfigProvider $siteConfigProvider
  179.      *
  180.      * @return $this
  181.      */
  182.     protected function buildPimcoreSettings(Request $request, array &$templateParamsUser $userKernelInterface $kernelExecutorInterface $maintenanceExecutorCsrfProtectionHandler $csrfProtectionSiteConfigProvider $siteConfigProvider)
  183.     {
  184.         $config                $templateParams['config'];
  185.         $dashboardHelper       = new \Pimcore\Helper\Dashboard($user);
  186.         $customAdminEntrypoint $this->getParameter('pimcore_admin.custom_admin_route_name');
  187.         try {
  188.             $adminEntrypointUrl $this->generateUrl($customAdminEntrypoint, [], UrlGeneratorInterface::ABSOLUTE_URL);
  189.         } catch (Exception) {
  190.             // if the custom admin entrypoint is not defined, return null in the settings
  191.             $adminEntrypointUrl null;
  192.         }
  193.         $settings = [
  194.             'instanceId'          => $this->getInstanceId(),
  195.             'version'             => Version::getVersion(),
  196.             'build'               => Version::getRevision(),
  197.             'debug'               => \Pimcore::inDebugMode(),
  198.             'devmode'             => \Pimcore::inDevMode(),
  199.             'disableMinifyJs'     => \Pimcore::disableMinifyJs(),
  200.             'environment'         => $kernel->getEnvironment(),
  201.             'cached_environments' => Tool::getCachedSymfonyEnvironments(),
  202.             'sessionId'           => htmlentities(Session::getSessionId(), ENT_QUOTES'UTF-8'),
  203.             // languages
  204.             'language'         => $request->getLocale(),
  205.             'websiteLanguages' => Admin::reorderWebsiteLanguages(
  206.                 $this->getAdminUser(),
  207.                 $config['general']['valid_languages'],
  208.                 true
  209.             ),
  210.             // flags
  211.             'showCloseConfirmation'          => true,
  212.             'debug_admin_translations'       => (bool)$config['general']['debug_admin_translations'],
  213.             'document_generatepreviews'      => (bool)$config['documents']['generate_preview'],
  214.             'asset_disable_tree_preview'     => (bool)$config['assets']['disable_tree_preview'],
  215.             'chromium'                       => \Pimcore\Image\Chromium::isSupported(),
  216.             'htmltoimage'                    => \Pimcore\Image\HtmlToImage::isSupported(),
  217.             'videoconverter'                 => \Pimcore\Video::isAvailable(),
  218.             'asset_hide_edit'                => (bool)$config['assets']['hide_edit_image'],
  219.             'main_domain'                    => $config['general']['domain'],
  220.             'custom_admin_entrypoint_url'    => $adminEntrypointUrl,
  221.             'timezone'                       => $config['general']['timezone'],
  222.             'tile_layer_url_template'        => $config['maps']['tile_layer_url_template'],
  223.             'geocoding_url_template'         => $config['maps']['geocoding_url_template'],
  224.             'reverse_geocoding_url_template' => $config['maps']['reverse_geocoding_url_template'],
  225.             'asset_tree_paging_limit'        => $config['assets']['tree_paging_limit'],
  226.             'document_tree_paging_limit'     => $config['documents']['tree_paging_limit'],
  227.             'object_tree_paging_limit'       => $config['objects']['tree_paging_limit'],
  228.             'maxmind_geoip_installed'        => (bool) $this->getParameter('pimcore.geoip.db_file'),
  229.             'hostname'                       => htmlentities(\Pimcore\Tool::getHostname(), ENT_QUOTES'UTF-8'),
  230.             'document_auto_save_interval' => $config['documents']['auto_save_interval'],
  231.             'object_auto_save_interval'   => $config['objects']['auto_save_interval'],
  232.             // perspective and portlets
  233.             'perspective'           => $templateParams['runtimePerspective'],
  234.             'availablePerspectives' => \Pimcore\Perspective\Config::getAvailablePerspectives($user),
  235.             'disabledPortlets'      => $dashboardHelper->getDisabledPortlets(),
  236.             // google analytics
  237.             'google_analytics_enabled' => (bool) $siteConfigProvider->isSiteReportingConfigured(),
  238.             // this stuff is used to decide whether the "add" button should be grayed out or not
  239.             'image-thumbnails-writeable'          => (new \Pimcore\Model\Asset\Image\Thumbnail\Config())->isWriteable(),
  240.             'video-thumbnails-writeable'          => (new \Pimcore\Model\Asset\Video\Thumbnail\Config())->isWriteable(),
  241.             'custom-reports-writeable'            => (new \Pimcore\Model\Tool\CustomReport\Config())->isWriteable(),
  242.             'document-types-writeable'            => (new DocType())->isWriteable(),
  243.             'web2print-writeable'                 => \Pimcore\Web2Print\Config::isWriteable(),
  244.             'predefined-properties-writeable'     => (new \Pimcore\Model\Property\Predefined())->isWriteable(),
  245.             'predefined-asset-metadata-writeable' => (new \Pimcore\Model\Metadata\Predefined())->isWriteable(),
  246.             'staticroutes-writeable'              => (new Staticroute())->isWriteable(),
  247.             'perspectives-writeable'              => \Pimcore\Perspective\Config::isWriteable(),
  248.             'custom-views-writeable'              => \Pimcore\CustomView\Config::isWriteable(),
  249.             'class-definition-writeable'          => isset($_SERVER['PIMCORE_CLASS_DEFINITION_WRITABLE']) ? (bool)$_SERVER['PIMCORE_CLASS_DEFINITION_WRITABLE'] : true,
  250.         ];
  251.         $this
  252.             ->addSystemVarSettings($settings)
  253.             ->addMaintenanceSettings($settings$maintenanceExecutor)
  254.             ->addMailSettings($settings$config)
  255.             ->addCustomViewSettings($settings);
  256.         $settings['csrfToken'] = $csrfProtection->getCsrfToken();
  257.         $templateParams['settings'] = $settings;
  258.         return $this;
  259.     }
  260.     /**
  261.      * @return string
  262.      */
  263.     private function getInstanceId()
  264.     {
  265.         $instanceId 'not-set';
  266.         try {
  267.             $instanceId $this->getParameter('secret');
  268.             $instanceId sha1(substr($instanceId3, -3));
  269.         } catch (\Exception $e) {
  270.             // nothing to do
  271.         }
  272.         return $instanceId;
  273.     }
  274.     /**
  275.      * @param array $settings
  276.      *
  277.      * @return $this
  278.      */
  279.     protected function addSystemVarSettings(array &$settings)
  280.     {
  281.         // upload limit
  282.         $max_upload filesize2bytes(ini_get('upload_max_filesize') . 'B');
  283.         $max_post filesize2bytes(ini_get('post_max_size') . 'B');
  284.         $upload_mb min($max_upload$max_post);
  285.         $settings['upload_max_filesize'] = (int) $upload_mb;
  286.         // session lifetime (gc)
  287.         $session_gc_maxlifetime ini_get('session.gc_maxlifetime');
  288.         if (empty($session_gc_maxlifetime)) {
  289.             $session_gc_maxlifetime 120;
  290.         }
  291.         $settings['session_gc_maxlifetime'] = (int)$session_gc_maxlifetime;
  292.         return $this;
  293.     }
  294.     /**
  295.      * @param array $settings
  296.      * @param ExecutorInterface $maintenanceExecutor
  297.      *
  298.      * @return $this
  299.      */
  300.     protected function addMaintenanceSettings(array &$settingsExecutorInterface $maintenanceExecutor)
  301.     {
  302.         // check maintenance
  303.         $maintenance_active false;
  304.         if ($lastExecution $maintenanceExecutor->getLastExecution()) {
  305.             if ((time() - $lastExecution) < 3660) { // maintenance script should run at least every hour + a little tolerance
  306.                 $maintenance_active true;
  307.             }
  308.         }
  309.         $settings['maintenance_active'] = $maintenance_active;
  310.         $settings['maintenance_mode'] = Admin::isInMaintenanceMode();
  311.         return $this;
  312.     }
  313.     /**
  314.      * @param array $settings
  315.      * @param Config $config
  316.      *
  317.      * @return $this
  318.      */
  319.     protected function addMailSettings(array &$settings$config)
  320.     {
  321.         //mail settings
  322.         $mailIncomplete false;
  323.         if (isset($config['email'])) {
  324.             if (\Pimcore::inDebugMode() && empty($config['email']['debug']['email_addresses'])) {
  325.                 $mailIncomplete true;
  326.             }
  327.             if (empty($config['email']['sender']['email'])) {
  328.                 $mailIncomplete true;
  329.             }
  330.         }
  331.         $settings['mail'] = !$mailIncomplete;
  332.         $settings['mailDefaultAddress'] = $config['email']['sender']['email'] ?? null;
  333.         return $this;
  334.     }
  335.     /**
  336.      * @param array $settings
  337.      *
  338.      * @return $this
  339.      */
  340.     protected function addCustomViewSettings(array &$settings)
  341.     {
  342.         $cvData = [];
  343.         // still needed when publishing objects
  344.         $cvConfig \Pimcore\CustomView\Config::get();
  345.         if ($cvConfig) {
  346.             foreach ($cvConfig as $node) {
  347.                 $tmpData $node;
  348.                 // backwards compatibility
  349.                 $treeType $tmpData['treetype'] ? $tmpData['treetype'] : 'object';
  350.                 $rootNode Service::getElementByPath($treeType$tmpData['rootfolder']);
  351.                 if ($rootNode) {
  352.                     $tmpData['rootId'] = $rootNode->getId();
  353.                     $tmpData['allowedClasses'] = $tmpData['classes'] ?? null;
  354.                     $tmpData['showroot'] = (bool)$tmpData['showroot'];
  355.                     // Check if a user has privileges to that node
  356.                     if ($rootNode->isAllowed('list')) {
  357.                         $cvData[] = $tmpData;
  358.                     }
  359.                 }
  360.             }
  361.         }
  362.         $settings['customviews'] = $cvData;
  363.         return $this;
  364.     }
  365.     /**
  366.      * {@inheritdoc}
  367.      */
  368.     public function onKernelResponseEvent(ResponseEvent $event)
  369.     {
  370.         $event->getResponse()->headers->set('X-Frame-Options''deny'true);
  371.     }
  372. }