Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Classes/Controller/Frontend/SetupController.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
use TYPO3\CMS\Extbase\Object\Exception as ObjectException;
use TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException;
use TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException;
use TYPO3\CMS\Lang\LanguageService;
use TYPO3\CMS\Core\Localization\LanguageService;
use function get_class;
use function vsprintf;

Expand Down Expand Up @@ -93,7 +93,7 @@ public function __construct(
Context $context
)
{
parent::__construct();
//parent::__construct();

$this->frontendUserRepository = $frontendUserRepository;
$this->qrCodeGenerator = $qrCodeGenerator;
Expand Down
2 changes: 1 addition & 1 deletion Classes/Hook/FeLogin.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
use CodeFareith\CfGoogleAuthenticator\Utility\ExtensionBasicDataUtility;
use CodeFareith\CfGoogleAuthenticator\Utility\PathUtility;
use TYPO3\CMS\Core\Service\MarkerBasedTemplateService;
use TYPO3\CMS\Lang\LanguageService;
use TYPO3\CMS\Core\Localization\LanguageService;

/**
* Hook for the TYPO3 CMS extension 'felogin'
Expand Down
7 changes: 7 additions & 0 deletions Classes/Hook/TCEMain.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,13 @@ public function processDatamap_preProcessFieldArray(
$otpInFieldArray = $otpInPostData;
}

$otpInFieldArray2 = &$fieldArray['tx_cfgoogleauthenticator_secret'];
$otpInPostData2 = $_POST['data']['be_users']['tx_cfgoogleauthenticator_secret'];

if ($otpInFieldArray2 === null && $otpInPostData2 !== null) {
$otpInFieldArray2 = $otpInPostData2;
}

$preProcessFieldArrayDTO = $this->getPreProcessFieldArrayDTO($fieldArray, $table, (int) $id, $dataHandler);
$result = $this->getGoogleAuthenticatorSetupHandler()->process($preProcessFieldArrayDTO);

Expand Down
36 changes: 19 additions & 17 deletions Classes/Hook/UserSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
use TYPO3\CMS\Fluid\View\StandaloneView;
use function sprintf;
use function vsprintf;
use TYPO3\CMS\Backend\Form\Element\AbstractFormElement;

/**
* Hook for the user settings
Expand All @@ -37,7 +38,7 @@
* @package CodeFareith\CfGoogleAuthenticator\Hook
* @since 1.0.0
*/
class UserSettings
class UserSettings extends AbstractFormElement
{
/*─────────────────────────────────────────────────────────────────────────────*\
Traits
Expand Down Expand Up @@ -71,21 +72,20 @@ class UserSettings
* @return string
* @throws Exception
*/
public function createSecretField(array $data): string
public function render(): array
{
$this->data = $data;

$result = $this->initializeResultArray();
$authenticationSecret = $this->getAuthenticationSecret();
$templateView = $this->initializeTemplateView();
$isEnabled = $this->isGoogleAuthenticatorEnabled();
$qrCodeUri = $this->getQrCodeGenerator()->generateUri($authenticationSecret);

$prefix = '';
if ($data['table'] !== null) {
$prefix .= sprintf('[%s]', $data['table']);
if ($this->data['tableName'] !== null) {
$prefix .= sprintf('[%s]', $this->data['tableName']);
}
if ($data['row']['uid'] !== null) {
$prefix .= sprintf('[%s]', (string)$data['row']['uid']);
if ($data['databaseRow']['uid'] !== null) {
$prefix .= sprintf('[%s]', (string)$this->data['databaseRow']['uid']);
}

$templateView->assignMultiple(
Expand All @@ -97,7 +97,9 @@ public function createSecretField(array $data): string
]
);

return $templateView->render();
$result['html'] = $templateView->render();

return $result;
}

private function initializeTemplateView(): StandaloneView
Expand Down Expand Up @@ -146,15 +148,15 @@ private function getLayer(): string
{
$layer = '';

if ($this->data['table'] === 'fe_users') {
if ($this->data['tableName'] === 'fe_users') {
$layer = 'Frontend';
} elseif ($this->data['table'] === 'be_users') {
} elseif ($this->data['tableName'] === 'be_users') {
$layer = 'Backend';
}

$dispatcher = GeneralUtility::makeInstance(Dispatcher::class);
$signalArguments = [
'table' => $this->data['table'],
'table' => $this->data['tableName'],
'layer' => $layer,
'caller' => $this,
];
Expand All @@ -169,7 +171,7 @@ private function getLayer(): string

private function getUsername(): string
{
return $this->data['row']['username'] ?? '';
return $this->data['databaseRow']['username'] ?? '';
}

/**
Expand All @@ -195,7 +197,7 @@ private function getAuthenticationSecret(): AuthenticationSecret
private function getSecretKey(): string
{
if ($this->isGoogleAuthenticatorEnabled()) {
$secretKey = (string) $this->data['row']['tx_cfgoogleauthenticator_secret'];
$secretKey = (string) $this->data['databaseRow']['tx_cfgoogleauthenticator_secret'];
} else {
$secretKey = Base32Utility::generateRandomString(16);
}
Expand All @@ -205,10 +207,10 @@ private function getSecretKey(): string

private function isGoogleAuthenticatorEnabled(): bool
{
if ($this->data['type'] === 'user' && !is_array($this->data['row'])) {
$this->data['row'] = $GLOBALS['BE_USER']->user;
if ($this->data['parameterArray']['fieldConf']['config']['type'] === 'user' && !is_array($this->data['databaseRow'])) {
$this->data['databaseRow'] = $GLOBALS['BE_USER']->user;
}
return (bool) $this->data['row']['tx_cfgoogleauthenticator_enabled'];
return (bool) $this->data['databaseRow']['tx_cfgoogleauthenticator_enabled'];
}

private function getQrCodeGenerator(): QrCodeGeneratorInterface
Expand Down
227 changes: 227 additions & 0 deletions Classes/Hook/UserSettingsProfile.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
<?php

declare(strict_types=1);
/**
* Class UserSettings
*
* @author Robin 'codeFareith' von den Bergen <robinvonberg@gmx.de>
* @copyright (c) 2018-2019 by Robin von den Bergen
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @version 1.0.0
*
* @link https://github.com/codeFareith/cf_google_authenticator
* @see https://www.fareith.de
* @see https://typo3.org
*/

namespace CodeFareith\CfGoogleAuthenticator\Hook;

use CodeFareith\CfGoogleAuthenticator\Domain\Immutable\AuthenticationSecret;
use CodeFareith\CfGoogleAuthenticator\Service\GoogleQrCodeGenerator;
use CodeFareith\CfGoogleAuthenticator\Service\QrCodeGeneratorInterface;
use CodeFareith\CfGoogleAuthenticator\Traits\GeneralUtilityObjectManager;
use CodeFareith\CfGoogleAuthenticator\Utility\Base32Utility;
use CodeFareith\CfGoogleAuthenticator\Utility\PathUtility;
use Exception;
use TYPO3\CMS\Extbase\SignalSlot\Dispatcher;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Fluid\View\StandaloneView;
use function sprintf;
use function vsprintf;

/**
* Hook for the user settings
*
* This class hooks into the backend user settings,
* to extend the view by creating a secret key and an image of
* the QR code for the Google Authenticator.
*
* @package CodeFareith\CfGoogleAuthenticator\Hook
* @since 1.0.0
*/
class UserSettingsProfile
{
/*─────────────────────────────────────────────────────────────────────────────*\
Traits
\*─────────────────────────────────────────────────────────────────────────────*/
use GeneralUtilityObjectManager;

/*─────────────────────────────────────────────────────────────────────────────*\
Properties
\*─────────────────────────────────────────────────────────────────────────────*/
/**
* @var mixed[]
*/
protected $data;

/**
* @var AuthenticationSecret
*/
private $authenticationSecret;

/**
* @var QrCodeGeneratorInterface
*/
private $qrCodeGenerator;

/*─────────────────────────────────────────────────────────────────────────────*\
Methods
\*─────────────────────────────────────────────────────────────────────────────*/
/**
* @param mixed[] $data
*
* @return string
* @throws Exception
*/
public function createSecretField(array $data): string
{
$result = $this->data;
$data = $result;
$authenticationSecret = $this->getAuthenticationSecret();
$templateView = $this->initializeTemplateView();
$isEnabled = $this->isGoogleAuthenticatorEnabled();
$qrCodeUri = $this->getQrCodeGenerator()->generateUri($authenticationSecret);

$prefix = '';
if ($this->data['tableName'] !== null) {
$prefix .= sprintf('[%s]', $this->data['tableName']);
}
if ($data['databaseRow']['uid'] !== null) {
$prefix .= sprintf('[%s]', (string)$this->data['databaseRow']['uid']);
}

$templateView->assignMultiple(
[
'prefix' => $prefix,
'isEnabled' => $isEnabled,
'qrCodeUri' => $qrCodeUri,
'authenticatorSecret' => $this->getAuthenticationSecret()->getSecretKey(),
]
);

$result = $templateView->render();

return $result;
}

private function initializeTemplateView(): StandaloneView
{
$templatePath = $this->getTemplatePath();

/** @var StandaloneView $templateView */
$templateView = $this->objectManager()->get(StandaloneView::class);
$templateView->setLayoutRootPaths([$templatePath . 'Layouts/']);
$templateView->setPartialRootPaths([$templatePath . 'Partials/']);
$templateView->setTemplateRootPaths([$templatePath . 'Templates/']);

$templateView->setTemplatePathAndFilename(
GeneralUtility::getFileAbsFileName(
PathUtility::makeExtensionPath('Resources/Private/Templates/Backend/UserSettings.html')
)
);

return $templateView;
}

private function getTemplatePath(): string
{
return GeneralUtility::getFileAbsFileName(
PathUtility::makeExtensionPath('Resources/Private/')
);
}

private function getIssuer(): string
{
return vsprintf(
'%s - %s',
[
$this->getSiteName(),
$this->getLayer(),
]
);
}

private function getSiteName(): string
{
return $GLOBALS['TYPO3_CONF_VARS']['SYS']['sitename'];
}

private function getLayer(): string
{
$layer = '';

if ($this->data['tableName'] === 'fe_users') {
$layer = 'Frontend';
} elseif ($this->data['tableName'] === 'be_users') {
$layer = 'Backend';
}

$dispatcher = GeneralUtility::makeInstance(Dispatcher::class);
$signalArguments = [
'table' => $this->data['tableName'],
'layer' => $layer,
'caller' => $this,
];
$signalArguments = $dispatcher->dispatch(
__CLASS__,
'defineIssuerLayer',
$signalArguments
);

return $signalArguments['layer'];
}

private function getUsername(): string
{
return $this->data['databaseRow']['username'] ?? '';
}

/**
* @throws Exception
*/
private function getAuthenticationSecret(): AuthenticationSecret
{
if ($this->authenticationSecret === null) {
$this->authenticationSecret = $this->objectManager()->get(
AuthenticationSecret::class,
$this->getIssuer(),
$this->getUsername(),
$this->getSecretKey()
);
}

return $this->authenticationSecret;
}

/**
* @throws Exception
*/
private function getSecretKey(): string
{
if ($this->isGoogleAuthenticatorEnabled()) {
$secretKey = (string) $this->data['databaseRow']['tx_cfgoogleauthenticator_secret'];
} else {
$secretKey = Base32Utility::generateRandomString(16);
}

return $secretKey;
}

private function isGoogleAuthenticatorEnabled(): bool
{
if ($this->data['parameterArray']['fieldConf']['config']['type'] === 'user' && !is_array($this->data['databaseRow'])) {
$this->data['databaseRow'] = $GLOBALS['BE_USER']->user;
}
return (bool) $this->data['databaseRow']['tx_cfgoogleauthenticator_enabled'];
}

private function getQrCodeGenerator(): QrCodeGeneratorInterface
{
if ($this->qrCodeGenerator === null) {
$this->qrCodeGenerator = $this->objectManager()->get(GoogleQrCodeGenerator::class);
}

return $this->qrCodeGenerator;
}
}
10 changes: 10 additions & 0 deletions Configuration/Extbase/Persistence/Classes.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

return [
\CodeFareith\CfGoogleAuthenticator\Domain\Model\FrontendUser::class => [
'tableName' => 'fe_users',
],
\CodeFareith\CfGoogleAuthenticator\Domain\Model\BackendUser::class => [
'tableName' => 'be_users',
],
];
2 changes: 1 addition & 1 deletion Configuration/TCA/Overrides/be_users.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ static function () {
),
'config' => [
'type' => 'user',
'userFunc' => \CodeFareith\CfGoogleAuthenticator\Hook\UserSettings::class . '->createSecretField',
'renderType' => 'TwoFactorAuth',
],
],
]
Expand Down
Loading