[TASK] Move BE User initialization into PSR-15 middleware 93/55793/3
authorBenni Mack <benni@typo3.org>
Mon, 19 Feb 2018 09:14:54 +0000 (10:14 +0100)
committerChristian Kuhn <lolli@schwarzbu.ch>
Mon, 19 Feb 2018 10:47:57 +0000 (11:47 +0100)
The initialization of a Backend user for Frontend Contexts is currently
bound to TSFE, however, the only parts where TSFE is actually
needed is to set the flag "beUserLogin".

Additionally, the initialization of the Language object is now
moved into the middleware, directly after the set up of $GLOBALS['BE_USER']
to allow the admin panel to use $GLOBALS['LANG'] as well.

Further steps are to deprecate "$TSFE->initializeBackendUser()" method,
and to deprecate the hooks, as they can now be implemented as PSR-15
middlewares.

Additional cleanups on the Authentication object will follow separately
once all Middlewares and the Request object are in place.

For now, this patch aims to extract the logic and keep maximum backwards-
compatibility.

Resolves: #83959
Releases: master
Change-Id: Ia4055f2d3671e9c14e492baa4eea724d989e9521
Reviewed-on: https://review.typo3.org/55793
Reviewed-by: Benjamin Franzke <bfr@qbus.de>
Tested-by: Benjamin Franzke <bfr@qbus.de>
Tested-by: TYPO3com <no-reply@typo3.com>
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
typo3/sysext/frontend/Classes/Http/RequestHandler.php
typo3/sysext/frontend/Classes/Middleware/BackendUserAuthenticator.php [new file with mode: 0644]
typo3/sysext/frontend/Configuration/RequestMiddlewares.php

index 78faf1a..0a64033 100644 (file)
@@ -28,7 +28,6 @@ use TYPO3\CMS\Core\TimeTracker\TimeTracker;
 use TYPO3\CMS\Core\Utility\GeneralUtility;
 use TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController;
 use TYPO3\CMS\Frontend\Page\PageGenerator;
-use TYPO3\CMS\Frontend\View\AdminPanelView;
 
 /**
  * This is the main entry point of the TypoScript driven standard front-end
@@ -87,21 +86,10 @@ class RequestHandler implements RequestHandlerInterface, PsrRequestHandlerInterf
         /** @var TypoScriptFrontendController $controller */
         $controller = $GLOBALS['TSFE'];
 
-        // Initializing a possible logged-in Backend User
-        /** @var $GLOBALS['BE_USER'] \TYPO3\CMS\Backend\FrontendBackendUserAuthentication */
-        $GLOBALS['BE_USER'] = $controller->initializeBackendUser();
-
         // Process the ID, type and other parameters.
         // After this point we have an array, $page in TSFE, which is the page-record
         // of the current page, $id.
         $this->timeTracker->push('Process ID', '');
-        // Initialize admin panel since simulation settings are required here:
-        if ($controller->isBackendUserLoggedIn()) {
-            $GLOBALS['BE_USER']->initializeAdminPanel();
-            $this->bootstrap
-                    ->initializeBackendRouter()
-                    ->loadExtTables();
-        }
         $controller->checkAlternativeIdMethods();
         $controller->clear_preview();
         $controller->determineId();
@@ -128,9 +116,6 @@ class RequestHandler implements RequestHandlerInterface, PsrRequestHandlerInterf
         // Admin Panel & Frontend editing
         if ($controller->isBackendUserLoggedIn()) {
             $GLOBALS['BE_USER']->initializeFrontendEdit();
-            if ($GLOBALS['BE_USER']->adminPanel instanceof AdminPanelView) {
-                $this->bootstrap->initializeLanguageObject();
-            }
             if ($GLOBALS['BE_USER']->frontendEdit instanceof FrontendEditingController) {
                 $GLOBALS['BE_USER']->frontendEdit->initConfigOptions();
             }
diff --git a/typo3/sysext/frontend/Classes/Middleware/BackendUserAuthenticator.php b/typo3/sysext/frontend/Classes/Middleware/BackendUserAuthenticator.php
new file mode 100644 (file)
index 0000000..a415d65
--- /dev/null
@@ -0,0 +1,114 @@
+<?php
+declare(strict_types = 1);
+namespace TYPO3\CMS\Frontend\Middleware;
+
+/*
+ * This file is part of the TYPO3 CMS project.
+ *
+ * It is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License, either version 2
+ * of the License, or any later version.
+ *
+ * For the full copyright and license information, please read the
+ * LICENSE.txt file that was distributed with this source code.
+ *
+ * The TYPO3 project - inspiring people to share!
+ */
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\MiddlewareInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+use TYPO3\CMS\Backend\FrontendBackendUserAuthentication;
+use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
+use TYPO3\CMS\Core\Core\Bootstrap;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
+/**
+ * This middleware authenticates a Backend User (be_user) (pre)-viewing a frontend page.
+ *
+ * This middleware also ensures that $GLOBALS['LANG'] is available, however it is possible that
+ * a different middleware later-on might unset the BE_USER as he/she is not allowed to preview a certain
+ * page due to rights management. As this can only happen once the page ID is resolved, this will happen
+ * after the routing middleware.
+ *
+ * Currently, this middleware depends on the availability of $GLOBALS['TSFE'], however, this is solely
+ * due to backwards-compatibility and will be disabled in the future.
+ */
+class BackendUserAuthenticator implements MiddlewareInterface
+{
+    /**
+     * Creates a frontend user authentication object, tries to authenticate a user
+     * and stores the object in $GLOBALS['TSFE']->fe_user.
+     *
+     * @param ServerRequestInterface $request
+     * @param RequestHandlerInterface $handler
+     * @return ResponseInterface
+     */
+    public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
+    {
+        // PRE BE_USER HOOK
+        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['preBeUser'] ?? [] as $_funcRef) {
+            $_params = [];
+            GeneralUtility::callUserFunction($_funcRef, $_params, $GLOBALS['TSFE']);
+        }
+
+        // Initializing a possible logged-in Backend User
+        // If the backend cookie is set,
+        // we proceed and check if a backend user is logged in.
+        $GLOBALS['TSFE']->beUserLogin = false;
+        $backendUserObject = null;
+        if (isset($request->getCookieParams()[BackendUserAuthentication::getCookieName()])) {
+            $backendUserObject = $this->initializeBackendUser();
+            // If the user is active now, let the controller know
+            if ($backendUserObject instanceof FrontendBackendUserAuthentication && !empty($backendUserObject->user['uid'])) {
+                $GLOBALS['TSFE']->beUserLogin = true;
+            }
+        }
+
+        $GLOBALS['BE_USER'] = $backendUserObject;
+
+        // POST BE_USER HOOK
+        $_params = [
+            'BE_USER' => &$GLOBALS['BE_USER']
+        ];
+        foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/index_ts.php']['postBeUser'] ?? [] as $_funcRef) {
+            GeneralUtility::callUserFunction($_funcRef, $_params, $GLOBALS['TSFE']);
+        }
+
+        // Load specific dependencies which are necessary for a valid Backend User
+        // like $GLOBALS['LANG'] for labels in the language of the BE User, the router, and ext_tables.php for all modules
+        // So things like Frontend Editing and Admin Panel can use this for generating links to the TYPO3 Backend.
+        if ($GLOBALS['BE_USER'] instanceof FrontendBackendUserAuthentication) {
+            Bootstrap::getInstance()
+                ->initializeLanguageObject()
+                ->initializeBackendRouter()
+                ->loadExtTables();
+            // Initialize admin panel since simulation settings are required here
+            $GLOBALS['BE_USER']->initializeAdminPanel();
+        }
+
+        return $handler->handle($request);
+    }
+
+    /**
+     * Creates the backend user object and returns it.
+     *
+     * @return FrontendBackendUserAuthentication|null the backend user object or null if there was no valid user found
+     */
+    public function initializeBackendUser()
+    {
+        // New backend user object
+        $backendUserObject = GeneralUtility::makeInstance(FrontendBackendUserAuthentication::class);
+        $backendUserObject->start();
+        $backendUserObject->unpack_uc();
+        if (!empty($backendUserObject->user['uid'])) {
+            $backendUserObject->fetchGroupData();
+        }
+        // Unset the user initialization if any setting / restriction applies
+        if (!$backendUserObject->checkBackendAccessSettingsFromInitPhp() || empty($backendUserObject->user['uid'])) {
+            $backendUserObject = null;
+        }
+        return $backendUserObject;
+    }
+}
index 83c386b..2d836ef 100644 (file)
@@ -69,5 +69,11 @@ return [
                 'typo3/cms-frontend/tsfe',
             ]
         ],
+        'typo3/cms-frontend/backend-user-authentication' => [
+            'target' => \TYPO3\CMS\Frontend\Middleware\BackendUserAuthenticator::class,
+            'after' => [
+                'typo3/cms-frontend/tsfe',
+            ]
+        ],
     ]
 ];