FluidTYPO3 / flux

TYPO3 extension Flux: Dynamic Fluid FlexForms
https://fluidtypo3.org
148 stars 214 forks source link

felogin plugin password recovery broken with version 10.0.x #2126

Closed sdelcroix closed 10 months ago

sdelcroix commented 10 months ago

Hi :)

On TYPO3v11, when I click on the "forgot password" link of felogin frontend plugin, I got the error saying "Either "$GLOBALS['TYPO3_CONF_VARS']['MAIL']['defaultMailFromName']" or extension key "plugin.tx_felogin_login.settings.email_fromName" cannot be empty!".

After debugging, I noticed that plugin.tx_felogin_login.settings was empty.

It's empty because $configurationManager->getConfiguration(ConfigurationManager::CONFIGURATION_TYPE_SETTINGS); instanciates a TYPO3\CMS\Extbase\Configuration\BackendConfigurationManagerand not a TYPO3\CMS\Extbase\Configuration\FrontendConfigurationManager.

After digging more, it's because $GLOBALS['TYPO3_REQUEST'] is null in this part of Extbase ConfigurationManager :

protected function initializeConcreteConfigurationManager(): void
{
    if (($GLOBALS['TYPO3_REQUEST'] ?? null) instanceof ServerRequestInterface
            && ApplicationType::fromRequest($GLOBALS['TYPO3_REQUEST'])->isFrontend()
        ) {
           $this->concreteConfigurationManager = $this->container->get(FrontendConfigurationManager::class);
        } else {
            $this->concreteConfigurationManager = $this->container->get(BackendConfigurationManager::class);
        }
    }

Some more debugging stuff leads me to the fact that it may be related to FluidTYPO3\Flux\Service\TypoScriptService that gets ConfigurationManagerInterface injected at a time where $GLOBALS['TYPO3_REQUEST'] is null.

To reproduce this issue :

  1. Have TYPO3 11.5.30
  2. Have Flux 10.0.3 installed and activated
  3. Have a Flux-based extension installed and activated (you don't need to have the flux-based content of this extension on the page you are testing)
  4. Put a felogin plugin on a page and check the forgot password option in it
  5. Configure the following TypoScript settings : either styles.content.loginform.emailFrom and styles.content.loginform.emailFromName in Constants OR plugin.tx_felogin_login.settings.email_from and plugin.tx_felogin_login.settings.email_fromName in Setup
  6. On the frontend, click on the forgot password link below the login form
  7. See the error

Our Flux-based extension registers provider like this : \FluidTYPO3\Flux\Core::registerProviderExtensionKey('Rvvnfluidcolumns', 'Content');

Our Content Controller is empty :

namespace RVVN\Rvvnfluidcolumns\Controller;

use FluidTYPO3\Flux\Controller\AbstractFluxController;
/**
 * Completely vanilla Flux controller.
 *
 * Used to render custom CType templates when no custom
 * controller exists for those.
 */
class ContentController extends AbstractFluxController
{
}

TypoScript setup is very simple :

`tt_content.rvvnfluidcolumns_example.templateName = FluidContent`
sdelcroix commented 10 months ago

Follow up

I kept debugging and found that if I replace ConfigurationManager by ConfigurationManagerInterface in TYPO3\CMS\FrontendLogin\Configuration\RecoveryConfiguration::__construct, the felogin plugin settings are not empty.

Here is the dependency injection sequence with this change :

/**
     * Gets the private 'TYPO3\CMS\FrontendLogin\Service\RecoveryService' shared autowired service.
     *
     * @return \TYPO3\CMS\FrontendLogin\Service\RecoveryService
     */
    protected function getRecoveryServiceService()
    {
        $a = ($this->services['FluidTYPO3\\Flux\\Integration\\Overrides\\ChimeraConfigurationManager'] ?? ($this->services['FluidTYPO3\\Flux\\Integration\\Overrides\\ChimeraConfigurationManager'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceForDi(\FluidTYPO3\Flux\Integration\Overrides\ChimeraConfigurationManager::class, $this)));

        $b = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceForDi(\TYPO3\CMS\FrontendLogin\Configuration\RecoveryConfiguration::class, ($this->services['TYPO3\\CMS\\Core\\Context\\Context'] ?? $this->getContextService()), $a, ($this->privates['TYPO3\\CMS\\Core\\Crypto\\Random'] ?? ($this->privates['TYPO3\\CMS\\Core\\Crypto\\Random'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceForDi(\TYPO3\CMS\Core\Crypto\Random::class))), ($this->services['TYPO3\\CMS\\Extbase\\Security\\Cryptography\\HashService'] ?? $this->getHashServiceService()));
        $b->setLogger(($this->services['_early.TYPO3\\CMS\\Core\\Log\\LogManager'] ?? $this->get('_early.TYPO3\\CMS\\Core\\Log\\LogManager', 1))->getLogger('TYPO3\\CMS\\FrontendLogin\\Configuration\\RecoveryConfiguration'));
        $c = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceForDi(\TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder::class);
        $c->injectConfigurationManager($a);
        $c->injectExtensionService(($this->services['TYPO3\\CMS\\Extbase\\Service\\ExtensionService'] ?? $this->getExtensionServiceService()));
        $c->initializeObject();

        return $this->privates['TYPO3\\CMS\\FrontendLogin\\Service\\RecoveryService'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceForDi(\TYPO3\CMS\FrontendLogin\Service\RecoveryService::class, ($this->services['TYPO3\\CMS\\Core\\Mail\\Mailer'] ?? $this->getMailerService()), ($this->services['Psr\\EventDispatcher\\EventDispatcherInterface_decorated_1'] ?? $this->getEventDispatcherInterfaceDecorated1Service()), ($this->services['TYPO3\\CMS\\Extbase\\Configuration\\ConfigurationManager'] ?? $this->getConfigurationManagerService()), $b, $c, ($this->privates['TYPO3\\CMS\\FrontendLogin\\Domain\\Repository\\FrontendUserRepository'] ?? $this->getFrontendUserRepository4Service()));
    }

To compare, here is the dependency injection sequence that throw error :

/**
     * Gets the private 'TYPO3\CMS\FrontendLogin\Service\RecoveryService' shared autowired service.
     *
     * @return \TYPO3\CMS\FrontendLogin\Service\RecoveryService
     */
    protected function getRecoveryServiceService()
    {
        $a = ($this->services['TYPO3\\CMS\\Extbase\\Configuration\\ConfigurationManager'] ?? $this->getConfigurationManagerService());
        $b = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceForDi(\TYPO3\CMS\FrontendLogin\Configuration\RecoveryConfiguration::class, ($this->services['TYPO3\\CMS\\Core\\Context\\Context'] ?? $this->getContextService()), $a, ($this->privates['TYPO3\\CMS\\Core\\Crypto\\Random'] ?? ($this->privates['TYPO3\\CMS\\Core\\Crypto\\Random'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceForDi(\TYPO3\CMS\Core\Crypto\Random::class))), ($this->services['TYPO3\\CMS\\Extbase\\Security\\Cryptography\\HashService'] ?? $this->getHashServiceService()));
        $b->setLogger(($this->services['_early.TYPO3\\CMS\\Core\\Log\\LogManager'] ?? $this->get('_early.TYPO3\\CMS\\Core\\Log\\LogManager', 1))->getLogger('TYPO3\\CMS\\FrontendLogin\\Configuration\\RecoveryConfiguration'));
        $c = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceForDi(\TYPO3\CMS\Extbase\Mvc\Web\Routing\UriBuilder::class);
        $c->injectConfigurationManager(($this->services['FluidTYPO3\\Flux\\Integration\\Overrides\\ChimeraConfigurationManager'] ?? ($this->services['FluidTYPO3\\Flux\\Integration\\Overrides\\ChimeraConfigurationManager'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceForDi(\FluidTYPO3\Flux\Integration\Overrides\ChimeraConfigurationManager::class, $this))));
        $c->injectExtensionService(($this->services['TYPO3\\CMS\\Extbase\\Service\\ExtensionService'] ?? $this->getExtensionServiceService()));
        $c->initializeObject();

        return $this->privates['TYPO3\\CMS\\FrontendLogin\\Service\\RecoveryService'] = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstanceForDi(\TYPO3\CMS\FrontendLogin\Service\RecoveryService::class, ($this->services['TYPO3\\CMS\\Core\\Mail\\Mailer'] ?? $this->getMailerService()), ($this->services['Psr\\EventDispatcher\\EventDispatcherInterface_decorated_1'] ?? $this->getEventDispatcherInterfaceDecorated1Service()), $a, $b, $c, ($this->privates['TYPO3\\CMS\\FrontendLogin\\Domain\\Repository\\FrontendUserRepository'] ?? $this->getFrontendUserRepository4Service()));
    }
sdelcroix commented 10 months ago

If I understood what I've debugged, the sequence is :

  1. When FluidTYPO3\Flux\Service\TypoScriptService is injected early at boot, ChimeraConfigurationManager::initializeConcreteConfigurationManager(...) calls TYPO3\CMS\Extbase\Configuration\ConfigurationManager::initializeConcreteConfigurationManager(...)
  2. At this time $GLOBALS['TYPO3_REQUEST'] is null, so Extbase ConfigurationManager instanciates a TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager as concreteConfigurationManager
  3. Later, in frontend, when dependency injection occurs for TYPO3\CMS\FrontendLogin\Configuration\RecoveryConfiguration, it uses the Extbase ConfigurationManager singleton instance and thus its concreteConfigurationManager
  4. As this concreteConfigurationManager is a TYPO3\CMS\Extbase\Configuration\BackendConfigurationManager, it cannot retrieve the frontend plugin TS settings
Konafets commented 10 months ago

Can confirm this error. I also encounter it when try to clean up the flexform records via CLI

vendor/bin/typo3 cleanup:flexforms

Updates all database records which have a FlexForm field and the XML data does not match the chosen datastructure.
==================================================================================================================

 ! [NOTE] Found 1313 records with wrong FlexForms information.

Cleanup process starting now.
-----------------------------

Updated FlexForm in record "tt_content:1354".

Uncaught TYPO3 Exception TYPO3\CMS\Core\Http\ApplicationType::fromRequest(): Argument #1 ($request) must be of type Psr\Http\Message\ServerRequestInterface, null given, called in /Users/user/Sites/example.com/public/typo3conf/ext/flux/Classes/Service/RecordService.php on line 150
thrown in file /Users/user/Sites/example.com/public/typo3/sysext/core/Classes/Http/ApplicationType.php
in line 62

I deinstalled ext:flux and was able to repair the records without any further issue.

sdelcroix commented 10 months ago

@NamelessCoder I've just done a quick and unique test with the latest development and it seems to be working now.

No error and reset email has been sent.

Thank you very much ! 👍

steffen-hph commented 10 months ago

@NamelessCoder @sdelcroix Works for me too 👍

Thanks!

NamelessCoder commented 10 months ago

Closing as solved.

sdelcroix commented 10 months ago

Fun fact : https://review.typo3.org/c/Packages/TYPO3.CMS/+/80941