Skip to content
This repository has been archived by the owner on May 13, 2024. It is now read-only.

Commit

Permalink
[WIP][TASK] TYPO3 v12 compatibility
Browse files Browse the repository at this point in the history
  • Loading branch information
waldhacker1 committed Jun 23, 2023
1 parent dbd8ad9 commit 40ea391
Show file tree
Hide file tree
Showing 18 changed files with 293 additions and 136 deletions.
93 changes: 90 additions & 3 deletions Classes/Authentication/BackendAuthenticationService.php
Expand Up @@ -23,9 +23,9 @@
use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Core\Authentication\AbstractAuthenticationService;
use TYPO3\CMS\Core\Http\ImmediateResponseException;
use TYPO3\CMS\Core\Http\ServerRequestFactory;
use TYPO3\CMS\Core\Service\AbstractService;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use Waldhacker\Oauth2Client\Backend\LoginProvider\Oauth2LoginProvider;
use Waldhacker\Oauth2Client\Events\BackendUserLookupEvent;
Expand All @@ -35,7 +35,7 @@
use Waldhacker\Oauth2Client\Service\Oauth2Service;
use Waldhacker\Oauth2Client\Session\SessionManager;

class BackendAuthenticationService extends AbstractService
class BackendAuthenticationService
{
private array $loginData = [];
private Oauth2ProviderManager $oauth2ProviderManager;
Expand All @@ -47,6 +47,12 @@ class BackendAuthenticationService extends AbstractService
private ?ResourceOwnerInterface $remoteUser = null;
private string $action = '';

/**
* @var array service description array
*/
public array $info = [];


public function __construct(
Oauth2ProviderManager $oauth2ProviderManager,
Oauth2Service $oauth2Service,
Expand Down Expand Up @@ -199,12 +205,15 @@ private function verify(string $providerId, string $code, string $state, ServerR

private function buildCallbackUri(string $providerId): string
{
$now = (string)time();
return (string)$this->uriBuilder->buildUriFromRoute('login', [
'loginProvider' => Oauth2LoginProvider::PROVIDER_ID,
'oauth2-provider' => $providerId,
// TYPO3\CMS\Core\Authentication\BackendUserAuthentication->formfield_status
'login_status' => 'login',
'commandLI' => 'attempt'
'commandLI' => 'attempt',
'time' => $now,
'hmac' => GeneralUtility::hmac($now, BackendAuthenticationService::class),
], UriBuilder::ABSOLUTE_URL);
}

Expand All @@ -216,4 +225,82 @@ private function getRequest(): ServerRequestInterface
}
return $request;
}

/**
* Initialization of the service.
* This is a stub as needed by GeneralUtility::makeInstanceService()
*
* @internal this is part of the Service API which should be avoided to be used and only used within TYPO3 internally
*/
public function init(): bool
{
return true;
}

/**
* Resets the service.
* This is a stub as needed by GeneralUtility::makeInstanceService()
*
* @internal this is part of the Service API which should be avoided to be used and only used within TYPO3 internally
*/
public function reset()
{
// nothing to do
}

/**
* Returns the service key of the service
*
* @return string Service key
* @internal this is part of the Service API which should be avoided to be used and only used within TYPO3 internally
*/
public function getServiceKey()
{
return $this->info['serviceKey'];
}

/**
* Returns the title of the service
*
* @return string Service title
* @internal this is part of the Service API which should be avoided to be used and only used within TYPO3 internally
*/
public function getServiceTitle()
{
return $this->info['title'];
}

/**
* Returns service configuration values from the $TYPO3_CONF_VARS['SVCONF'] array
*
* @param string $optionName Name of the config option
* @param mixed $defaultValue Default configuration if no special config is available
* @param bool $includeDefaultConfig If set the 'default' config will be returned if no special config for this service is available (default: TRUE)
* @return mixed Configuration value for the service
* @internal this is part of the Service API which should be avoided to be used and only used within TYPO3 internally
*/
public function getServiceOption($optionName, $defaultValue = '', $includeDefaultConfig = true)
{
$config = null;
$serviceType = $this->info['serviceType'] ?? '';
$serviceKey = $this->info['serviceKey'] ?? '';
$svOptions = $GLOBALS['TYPO3_CONF_VARS']['SVCONF'][$serviceType] ?? [];
if (isset($svOptions[$serviceKey][$optionName])) {
$config = $svOptions[$serviceKey][$optionName];
} elseif ($includeDefaultConfig && isset($svOptions['default'][$optionName])) {
$config = $svOptions['default'][$optionName];
}
if (!isset($config)) {
$config = $defaultValue;
}
return $config;
}

/**
* @internal this is part of the Service API which should be avoided to be used and only used within TYPO3 internally
*/
public function getLastErrorArray(): array
{
return [];
}
}
3 changes: 2 additions & 1 deletion Classes/Controller/Backend/AbstractBackendController.php
Expand Up @@ -21,11 +21,12 @@
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Messaging\FlashMessageService;
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
use TYPO3\CMS\Core\Utility\GeneralUtility;

class AbstractBackendController
{
protected function addFlashMessage(string $message, string $title = '', int $severity = FlashMessage::INFO): void
protected function addFlashMessage(string $message, string $title = '', ContextualFeedbackSeverity $severity = ContextualFeedbackSeverity::INFO): void
{
GeneralUtility::makeInstance(FlashMessageService::class)->getMessageQueueByIdentifier()->enqueue(
GeneralUtility::makeInstance(FlashMessage::class, $message, $title, $severity, true)
Expand Down
35 changes: 10 additions & 25 deletions Classes/Controller/Backend/ManageProvidersController.php
Expand Up @@ -24,6 +24,7 @@
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
use TYPO3\CMS\Backend\Template\ModuleTemplate;
use TYPO3\CMS\Backend\Template\ModuleTemplateFactory;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Utility\ExtensionManagementUtility;
Expand All @@ -37,46 +38,41 @@ class ManageProvidersController extends AbstractBackendController
{
private Oauth2ProviderManager $oauth2ProviderManager;
private BackendUserRepository $backendUserRepository;
private ModuleTemplate $moduleTemplate;
private ModuleTemplateFactory $moduleTemplateFactory;
private UriBuilder $uriBuilder;
private ResponseFactoryInterface $responseFactory;
private IconFactory $iconFactory;

public function __construct(
Oauth2ProviderManager $oauth2ProviderManager,
BackendUserRepository $backendUserRepository,
ModuleTemplate $moduleTemplate,
ModuleTemplateFactory $moduleTemplate,
UriBuilder $uriBuilder,
ResponseFactoryInterface $responseFactory,
IconFactory $iconFactory
) {
$this->oauth2ProviderManager = $oauth2ProviderManager;
$this->backendUserRepository = $backendUserRepository;
$this->moduleTemplate = $moduleTemplate;
$this->moduleTemplateFactory = $moduleTemplate;
$this->uriBuilder = $uriBuilder;
$this->responseFactory = $responseFactory;
$this->iconFactory = $iconFactory;
}

public function __invoke(ServerRequestInterface $request): ResponseInterface
{
$this->addButtons($request);

$view = $this->initializeView('ManageProviders');
$view->assignMultiple([
$moduleTemplate = $this->moduleTemplateFactory->create($request);
$this->addButtons($request, $moduleTemplate);
$moduleTemplate->assignMultiple([
'providers' => $this->oauth2ProviderManager->getConfiguredBackendProviders(),
'activeProviders' => $this->backendUserRepository->getActiveProviders()
]);
$this->moduleTemplate->setContent($view->render());
$this->moduleTemplate->getPageRenderer()->addJsFile('EXT:oauth2_client/Resources/Public/JavaScript/register.js');
$response = $this->responseFactory->createResponse()->withHeader('Content-Type', 'text/html; charset=utf-8');
$response->getBody()->write($this->moduleTemplate->renderContent());
return $response;
return $moduleTemplate->renderResponse('Backend/ManageProviders');
}

private function addButtons(ServerRequestInterface $request): void
private function addButtons(ServerRequestInterface $request, ModuleTemplate $moduleTemplate): void
{
$buttonBar = $this->moduleTemplate->getDocHeaderComponent()->getButtonBar();
$buttonBar = $moduleTemplate->getDocHeaderComponent()->getButtonBar();

if (($returnUrl = $this->getReturnUrl($request)) !== '') {
$button = $buttonBar
Expand All @@ -96,17 +92,6 @@ private function addButtons(ServerRequestInterface $request): void
$buttonBar->addButton($reloadButton, ButtonBar::BUTTON_POSITION_RIGHT);
}

private function initializeView(string $templateName): ViewInterface
{
/** @var StandaloneView $view */
$view = GeneralUtility::makeInstance(StandaloneView::class);
$view->setTemplateRootPaths(['EXT:oauth2_client/Resources/Private/Templates/Backend']);
$view->setPartialRootPaths(['EXT:backend/Resources/Private/Partials']);
$view->setLayoutRootPaths(['EXT:backend/Resources/Private/Layouts']);
$view->setTemplate($templateName);
return $view;
}

private function getReturnUrl(ServerRequestInterface $request): string
{
$queryParams = $request->getQueryParams();
Expand Down
6 changes: 3 additions & 3 deletions Classes/Controller/Backend/Registration/VerifyController.php
Expand Up @@ -24,7 +24,7 @@
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Messaging\FlashMessage;
use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity;
use Waldhacker\Oauth2Client\Controller\Backend\AbstractBackendController;
use Waldhacker\Oauth2Client\Repository\BackendUserRepository;
use Waldhacker\Oauth2Client\Service\Oauth2ProviderManager;
Expand Down Expand Up @@ -120,7 +120,7 @@ public function __invoke(ServerRequestInterface $request): ResponseInterface
$this->addFlashMessage(
$this->getLanguageService()->sL('LLL:EXT:oauth2_client/Resources/Private/Language/locallang_be.xlf:flash.providerConfigurationAdded.description'),
$this->getLanguageService()->sL('LLL:EXT:oauth2_client/Resources/Private/Language/locallang_be.xlf:flash.providerConfigurationAdded.title'),
FlashMessage::OK
ContextualFeedbackSeverity::OK
);

$response = $this->responseFactory
Expand All @@ -136,7 +136,7 @@ private function redirectWithWarning(ServerRequestInterface $request): ResponseI
$this->addFlashMessage(
$this->getLanguageService()->sL('LLL:EXT:oauth2_client/Resources/Private/Language/locallang_be.xlf:flash.providerConfigurationFailed.description'),
$this->getLanguageService()->sL('LLL:EXT:oauth2_client/Resources/Private/Language/locallang_be.xlf:flash.providerConfigurationFailed.title'),
FlashMessage::WARNING
ContextualFeedbackSeverity::WARNING
);

$response = $this->responseFactory
Expand Down
Expand Up @@ -63,7 +63,7 @@ public function buildExpression(array $queriedTables, ExpressionBuilder $express
);
}

return $expressionBuilder->andX(...$constraints);
return $expressionBuilder->and(...$constraints);
}

public function isEnforced(): bool
Expand Down
Expand Up @@ -71,7 +71,7 @@ public function buildExpression(array $queriedTables, ExpressionBuilder $express
);
}

return $expressionBuilder->andX(...$constraints);
return $expressionBuilder->and(...$constraints);
}

public function isEnforced(): bool
Expand Down
85 changes: 85 additions & 0 deletions Classes/Events/Listener/GenerateRequestTokenListener.php
@@ -0,0 +1,85 @@
<?php

declare(strict_types = 1);

/*
* This file is part of the OAuth2 Client extension for TYPO3
* - (c) 2021 waldhacker UG (haftungsbeschränkt)
*
* 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!
*/

namespace Waldhacker\Oauth2Client\Events\Listener;

use TYPO3\CMS\Core\Authentication\Event\BeforeRequestTokenProcessedEvent;
use TYPO3\CMS\Core\Context\Context;
use TYPO3\CMS\Core\Security\RequestToken;
use Waldhacker\Oauth2Client\Backend\LoginProvider\Oauth2LoginProvider;

class GenerateRequestTokenListener
{
public function __construct(protected readonly Context $context)
{
}

public function __invoke(BeforeRequestTokenProcessedEvent $event): void
{
// todo
// wenn oauth cookie => get time from token from cookie
// wenn request within 5 sec => generate and set token

// $requestToken = RequestToken::create('core/user-auth/be');
// $event->setRequestToken($requestToken);

/*
$request = $event->getRequest();
$getParameters = $request->getQueryParams();
$postParameters = is_array($request->getParsedBody()) ? $request->getParsedBody() : [];
$loginProvider = $getParameters['loginProvider'] ?? null;
if ($loginProvider !== Oauth2LoginProvider::PROVIDER_ID) {
return;
}
$code = (string)($getParameters['code'] ?? '');
$state = (string)($getParameters['state'] ?? '');
$providerIdFromPost = (string)($postParameters['oauth2-provider'] ?? '');
$providerIdFromGet = (string)($getParameters['oauth2-provider'] ?? '');
$action = !empty($providerIdFromPost) && empty($code) && empty($state)
? 'authorize'
: (!empty($providerIdFromGet) && !empty($code) && !empty($state) ? 'verify' : 'invalid');
if ($action !== 'verify') {
return;
}
$requestToken = $event->getRequestToken();
if (!($requestToken instanceof RequestToken)) {
$event->setRequestToken(null);
return;
}
// check time of request within 5 sec
$now = $this->context->getAspect('date')->getDateTime();
$interval = new \DateInterval(sprintf('PT%dS', 5));
$moreThan5Seconds = $now > $requestToken->time->add($interval);
if ($moreThan5Seconds) {
$event->setRequestToken(null);
return;
}
*/
}
}

0 comments on commit 40ea391

Please sign in to comment.