From 43edcc80cbaffbed6fd591401357e23ca82fa0d2 Mon Sep 17 00:00:00 2001 From: Fritz Michael Gschwantner Date: Thu, 11 Aug 2022 12:10:24 +0200 Subject: [PATCH] Set login constants in request listener (see #4968) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Description ----------- - Commits ------- 829a2075 set login constants in request listener cc98d05b update tests 69755867 only set constants if framework was initialized 3a5bb255 code style df1a2b5f expect deprecation 7abe0f24 English please 7d72d580 simplify implementation 98a490da use getMode d60c2cba Merge remote-tracking branch 'origin/4.9' into set-login-constants-in… --- .../LegacyLoginConstantsListener.php | 39 +++++++++ core-bundle/src/Framework/ContaoFramework.php | 32 +++++-- core-bundle/src/Resources/config/listener.yml | 8 ++ .../tests/Framework/ContaoFrameworkTest.php | 87 +++++++++++++++---- 4 files changed, 141 insertions(+), 25 deletions(-) create mode 100644 core-bundle/src/EventListener/LegacyLoginConstantsListener.php diff --git a/core-bundle/src/EventListener/LegacyLoginConstantsListener.php b/core-bundle/src/EventListener/LegacyLoginConstantsListener.php new file mode 100644 index 00000000000..bb4425599d2 --- /dev/null +++ b/core-bundle/src/EventListener/LegacyLoginConstantsListener.php @@ -0,0 +1,39 @@ +framework = $framework; + } + + public function __invoke(RequestEvent $event): void + { + $this->framework->setLoginConstants(); + } +} diff --git a/core-bundle/src/Framework/ContaoFramework.php b/core-bundle/src/Framework/ContaoFramework.php index 87dcfd4ef28..4067f591718 100644 --- a/core-bundle/src/Framework/ContaoFramework.php +++ b/core-bundle/src/Framework/ContaoFramework.php @@ -61,6 +61,7 @@ class ContaoFramework implements ContaoFrameworkInterface, ContainerAwareInterfa private bool $isFrontend = false; private array $adapterCache = []; private array $hookListeners = []; + private bool $setLoginConstantsOnInit = false; public function __construct(RequestStack $requestStack, ScopeMatcher $scopeMatcher, TokenChecker $tokenChecker, Filesystem $filesystem, UrlGeneratorInterface $urlGenerator, string $projectDir, int $errorLevel, bool $legacyRouting) { @@ -171,6 +172,27 @@ public static function getNonce(): string return self::$nonce; } + /** + * @deprecated Deprecated since Contao 4.9, to be removed in Contao 5.0 + */ + public function setLoginConstants(): void + { + // If the framework has not been initialized yet, set the login constants on init (#4968) + if (!$this->isInitialized()) { + $this->setLoginConstantsOnInit = true; + + return; + } + + if ('FE' === $this->getMode()) { + \define('BE_USER_LOGGED_IN', $this->tokenChecker->hasBackendUser() && $this->tokenChecker->isPreviewMode()); + \define('FE_USER_LOGGED_IN', $this->tokenChecker->hasFrontendUser()); + } else { + \define('BE_USER_LOGGED_IN', false); + \define('FE_USER_LOGGED_IN', false); + } + } + /** * @deprecated Deprecated since Contao 4.0, to be removed in Contao 5.0 */ @@ -189,14 +211,8 @@ private function setConstants(): void } // Define the login status constants (see #4099, #5279) - if ('FE' === $this->getMode() && ($session = $this->getSession()) && $this->request->hasPreviousSession()) { - $session->start(); - - \define('BE_USER_LOGGED_IN', $this->tokenChecker->isPreviewMode()); - \define('FE_USER_LOGGED_IN', $this->tokenChecker->hasFrontendUser()); - } else { - \define('BE_USER_LOGGED_IN', false); - \define('FE_USER_LOGGED_IN', false); + if ($this->setLoginConstantsOnInit || null === $this->requestStack->getCurrentRequest()) { + $this->setLoginConstants(); } // Define the relative path to the installation (see #5339) diff --git a/core-bundle/src/Resources/config/listener.yml b/core-bundle/src/Resources/config/listener.yml index 3cf6172a74a..dc73b1c6ab3 100644 --- a/core-bundle/src/Resources/config/listener.yml +++ b/core-bundle/src/Resources/config/listener.yml @@ -337,6 +337,14 @@ services: tags: - { name: contao.callback, table: tl_module, target: fields.customTpl.options } + contao.listener.legacy_login_constants: + class: Contao\CoreBundle\EventListener\LegacyLoginConstantsListener + arguments: + - '@contao.framework' + tags: + # The priority must be lower than the one of the firewall listener (defaults to 8) + - { name: kernel.event_listener, priority: 7 } + contao.listener.page_trail_cache_tags: class: Contao\CoreBundle\EventListener\PageTrailCacheTagsListener arguments: diff --git a/core-bundle/tests/Framework/ContaoFrameworkTest.php b/core-bundle/tests/Framework/ContaoFrameworkTest.php index e452745f1aa..51109f874fa 100644 --- a/core-bundle/tests/Framework/ContaoFrameworkTest.php +++ b/core-bundle/tests/Framework/ContaoFrameworkTest.php @@ -70,15 +70,13 @@ public function testInitializesTheFrameworkWithAFrontEndRequest(): void $this->assertTrue(\defined('TL_ROOT')); $this->assertTrue(\defined('TL_REFERER_ID')); $this->assertTrue(\defined('TL_SCRIPT')); - $this->assertTrue(\defined('BE_USER_LOGGED_IN')); - $this->assertTrue(\defined('FE_USER_LOGGED_IN')); + $this->assertFalse(\defined('BE_USER_LOGGED_IN')); + $this->assertFalse(\defined('FE_USER_LOGGED_IN')); $this->assertTrue(\defined('TL_PATH')); $this->assertSame('FE', TL_MODE); $this->assertSame($this->getTempDir(), TL_ROOT); $this->assertSame('', TL_REFERER_ID); $this->assertSame('index.html', TL_SCRIPT); - $this->assertFalse(BE_USER_LOGGED_IN); - $this->assertFalse(FE_USER_LOGGED_IN); $this->assertSame('', TL_PATH); $this->assertSame('en', $GLOBALS['TL_LANGUAGE']); } @@ -104,15 +102,13 @@ public function testInitializesTheFrameworkWithABackEndRequest(): void $this->assertTrue(\defined('TL_ROOT')); $this->assertTrue(\defined('TL_REFERER_ID')); $this->assertTrue(\defined('TL_SCRIPT')); - $this->assertTrue(\defined('BE_USER_LOGGED_IN')); - $this->assertTrue(\defined('FE_USER_LOGGED_IN')); + $this->assertFalse(\defined('BE_USER_LOGGED_IN')); + $this->assertFalse(\defined('FE_USER_LOGGED_IN')); $this->assertTrue(\defined('TL_PATH')); $this->assertSame('BE', TL_MODE); $this->assertSame($this->getTempDir(), TL_ROOT); $this->assertSame('foobar', TL_REFERER_ID); $this->assertSame('contao/login', TL_SCRIPT); - $this->assertFalse(BE_USER_LOGGED_IN); - $this->assertFalse(FE_USER_LOGGED_IN); $this->assertSame('', TL_PATH); $this->assertSame('de', $GLOBALS['TL_LANGUAGE']); } @@ -190,15 +186,13 @@ public function testInitializesTheFrameworkWithAnInsecurePath(): void $this->assertTrue(\defined('TL_ROOT')); $this->assertTrue(\defined('TL_REFERER_ID')); $this->assertTrue(\defined('TL_SCRIPT')); - $this->assertTrue(\defined('BE_USER_LOGGED_IN')); - $this->assertTrue(\defined('FE_USER_LOGGED_IN')); + $this->assertFalse(\defined('BE_USER_LOGGED_IN')); + $this->assertFalse(\defined('FE_USER_LOGGED_IN')); $this->assertTrue(\defined('TL_PATH')); $this->assertSame('FE', TL_MODE); $this->assertSame($this->getTempDir(), TL_ROOT); $this->assertSame('', TL_REFERER_ID); $this->assertSame('index.php/index.html', TL_SCRIPT); - $this->assertFalse(BE_USER_LOGGED_IN); - $this->assertFalse(FE_USER_LOGGED_IN); $this->assertSame('/contao4/public', TL_PATH); } @@ -221,22 +215,80 @@ public function testInitializesTheFrameworkWithoutAScope(): void $this->assertTrue(\defined('TL_ROOT')); $this->assertTrue(\defined('TL_REFERER_ID')); $this->assertTrue(\defined('TL_SCRIPT')); - $this->assertTrue(\defined('BE_USER_LOGGED_IN')); - $this->assertTrue(\defined('FE_USER_LOGGED_IN')); + $this->assertFalse(\defined('BE_USER_LOGGED_IN')); + $this->assertFalse(\defined('FE_USER_LOGGED_IN')); $this->assertTrue(\defined('TL_PATH')); $this->assertNull(TL_MODE); $this->assertSame($this->getTempDir(), TL_ROOT); $this->assertSame('foobar', TL_REFERER_ID); $this->assertSame('contao/login', TL_SCRIPT); + $this->assertSame('', TL_PATH); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testDoesNotSetTheLoginConstantsOnInit(): void + { + $request = Request::create('/index.html'); + $request->attributes->set('_route', 'dummy'); + $request->attributes->set('_scope', 'frontend'); + + $framework = $this->mockFramework($request); + $framework->setContainer($this->getContainerWithContaoConfiguration()); + $framework->initialize(); + + $this->assertFalse(\defined('BE_USER_LOGGED_IN')); + $this->assertFalse(\defined('FE_USER_LOGGED_IN')); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + */ + public function testSetsTheLoginConstantsOnInitIfEnabled(): void + { + $request = Request::create('/index.html'); + $request->attributes->set('_route', 'dummy'); + $request->attributes->set('_scope', 'frontend'); + + $framework = $this->mockFramework($request); + $framework->setContainer($this->getContainerWithContaoConfiguration()); + + // Call setLoginConstants before initialize + $framework->setLoginConstants(); + + $framework->initialize(); + + $this->assertTrue(\defined('BE_USER_LOGGED_IN')); + $this->assertTrue(\defined('FE_USER_LOGGED_IN')); $this->assertFalse(BE_USER_LOGGED_IN); $this->assertFalse(FE_USER_LOGGED_IN); - $this->assertSame('', TL_PATH); } /** * @runInSeparateProcess * @preserveGlobalState disabled */ + public function testSetsTheLoginConstantsOnInitIfThereIsNoRequest(): void + { + $framework = $this->mockFramework(); + $framework->setContainer($this->getContainerWithContaoConfiguration()); + $framework->initialize(); + + $this->assertTrue(\defined('BE_USER_LOGGED_IN')); + $this->assertTrue(\defined('FE_USER_LOGGED_IN')); + $this->assertFalse(BE_USER_LOGGED_IN); + $this->assertFalse(FE_USER_LOGGED_IN); + } + + /** + * @runInSeparateProcess + * @preserveGlobalState disabled + * @group legacy + * @expectedDeprecation Using $_SESSION has been deprecated and will no longer work in Contao 5.0. Use the Symfony session instead. + */ public function testInitializesTheFrameworkInPreviewMode(): void { $beBag = new ArrayAttributeBag(); @@ -272,6 +324,7 @@ public function testInitializesTheFrameworkInPreviewMode(): void $framework = $this->getFramework($request, null, $tokenChecker); $framework->setContainer($this->getContainerWithContaoConfiguration()); $framework->initialize(); + $framework->setLoginConstants(); $this->assertTrue(\defined('TL_MODE')); $this->assertTrue(\defined('TL_START')); @@ -301,13 +354,13 @@ public function testDoesNotInitializeTheFrameworkTwice(): void { $scopeMatcher = $this->createMock(ScopeMatcher::class); $scopeMatcher - ->expects($this->exactly(2)) + ->expects($this->exactly(1)) ->method('isBackendRequest') ->willReturn(false) ; $scopeMatcher - ->expects($this->exactly(2)) + ->expects($this->exactly(1)) ->method('isFrontendRequest') ->willReturn(false) ;