Passed
Push — master ( 25a926...39145a )
by
unknown
20:30
created

initializeMfaConfiguration()   B

Complexity

Conditions 7
Paths 7

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 14
c 1
b 0
f 0
dl 0
loc 25
rs 8.8333
cc 7
nc 7
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the TYPO3 CMS project.
7
 *
8
 * It is free software; you can redistribute it and/or modify it under
9
 * the terms of the GNU General Public License, either version 2
10
 * of the License, or any later version.
11
 *
12
 * For the full copyright and license information, please read the
13
 * LICENSE.txt file that was distributed with this source code.
14
 *
15
 * The TYPO3 project - inspiring people to share!
16
 */
17
18
namespace TYPO3\CMS\Backend\Controller;
19
20
use Psr\Http\Message\ResponseInterface;
21
use Psr\Http\Message\ServerRequestInterface;
22
use TYPO3\CMS\Backend\Routing\UriBuilder;
23
use TYPO3\CMS\Backend\Template\ModuleTemplate;
24
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
25
use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderManifestInterface;
26
use TYPO3\CMS\Core\Authentication\Mfa\MfaProviderRegistry;
27
use TYPO3\CMS\Core\Localization\LanguageService;
28
use TYPO3\CMS\Core\Utility\GeneralUtility;
29
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
30
31
/**
32
 * Abstract class for mfa controllers (configuration and authentication)
33
 *
34
 * @internal This class is a specific Backend controller implementation and is not considered part of the Public TYPO3 API.
35
 */
36
abstract class AbstractMfaController
37
{
38
    protected ModuleTemplate $moduleTemplate;
39
    protected UriBuilder $uriBuilder;
40
    protected MfaProviderRegistry $mfaProviderRegistry;
41
    protected array $mfaTsConfig;
42
    protected bool $mfaRequired;
43
    protected array $allowedProviders;
44
    protected array $allowedActions = [];
45
    protected ?MfaProviderManifestInterface $mfaProvider = null;
46
    protected ?ViewInterface $view = null;
47
48
    public function __construct(
49
        ModuleTemplate $moduleTemplate,
50
        UriBuilder $uriBuilder,
51
        MfaProviderRegistry $mfaProviderRegistry
52
    ) {
53
        $this->moduleTemplate = $moduleTemplate;
54
        $this->uriBuilder = $uriBuilder;
55
        $this->mfaProviderRegistry = $mfaProviderRegistry;
56
        $this->initializeMfaConfiguration();
57
    }
58
59
    /**
60
     * Main action for handling the request and returning the response
61
     *
62
     * @param ServerRequestInterface $request
63
     * @return ResponseInterface
64
     */
65
    abstract public function handleRequest(ServerRequestInterface $request): ResponseInterface;
66
67
    protected function isActionAllowed(string $action): bool
68
    {
69
        return in_array($action, $this->allowedActions, true);
70
    }
71
72
    protected function isProviderAllowed(string $identifier): bool
73
    {
74
        return isset($this->allowedProviders[$identifier]);
75
    }
76
77
    protected function isValidIdentifier(string $identifier): bool
78
    {
79
        return $identifier !== ''
80
            && $this->isProviderAllowed($identifier)
81
            && $this->mfaProviderRegistry->hasProvider($identifier);
82
    }
83
84
    public function getLocalizedProviderTitle(): string
85
    {
86
        return $this->mfaProvider !== null ? $this->getLanguageService()->sL($this->mfaProvider->getTitle()) : '';
87
    }
88
89
    /**
90
     * Initialize MFA configuration based on TSconfig and global configuration
91
     */
92
    protected function initializeMfaConfiguration(): void
93
    {
94
        $this->mfaTsConfig = $this->getBackendUser()->getTSConfig()['auth.']['mfa.'] ?? [];
95
96
        // Set up required state based on user TSconfig and global configuration
97
        if (isset($this->mfaTsConfig['required'])) {
98
            // user TSconfig overrules global configuration
99
            $this->mfaRequired = (bool)($this->mfaTsConfig['required'] ?? false);
100
        } else {
101
            $globalConfig = (int)($GLOBALS['TYPO3_CONF_VARS']['BE']['requireMfa'] ?? 0);
102
            if ($globalConfig <= 1) {
103
                // 0 and 1 can directly be used by type-casting to boolean
104
                $this->mfaRequired = (bool)$globalConfig;
105
            } else {
106
                // check the admin / non-admin options
107
                $isAdmin = $this->getBackendUser()->isAdmin();
108
                $this->mfaRequired = ($globalConfig === 2 && !$isAdmin) || ($globalConfig === 3 && $isAdmin);
109
            }
110
        }
111
112
        // Set up allowed providers based on user TSconfig and user groupData
113
        $this->allowedProviders = array_filter($this->mfaProviderRegistry->getProviders(), function ($identifier) {
114
            return $this->getBackendUser()->check('mfa_providers', $identifier)
115
                && !GeneralUtility::inList(($this->mfaTsConfig['disableProviders'] ?? ''), $identifier);
116
        }, ARRAY_FILTER_USE_KEY);
117
    }
118
119
    protected function getBackendUser(): BackendUserAuthentication
120
    {
121
        return $GLOBALS['BE_USER'];
122
    }
123
124
    protected function getLanguageService(): LanguageService
125
    {
126
        return $GLOBALS['LANG'];
127
    }
128
}
129