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

MfaProviderRegistry::getProviders()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 1
c 1
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
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\Core\Authentication\Mfa;
19
20
use TYPO3\CMS\Core\Authentication\AbstractUserAuthentication;
21
22
/**
23
 * Registry for configuration providers which is called by the ConfigurationProviderPass
24
 *
25
 * @internal
26
 */
27
class MfaProviderRegistry
28
{
29
    /**
30
     * @var MfaProviderManifestInterface[]
31
     */
32
    protected array $providers = [];
33
34
    public function registerProvider(MfaProviderManifestInterface $provider): void
35
    {
36
        $this->providers[$provider->getIdentifier()] = $provider;
37
    }
38
39
    public function hasProvider(string $identifer): bool
40
    {
41
        return isset($this->providers[$identifer]);
42
    }
43
44
    public function hasProviders(): bool
45
    {
46
        return $this->providers !== [];
47
    }
48
49
    public function getProvider(string $identifier): MfaProviderManifestInterface
50
    {
51
        if (!$this->hasProvider($identifier)) {
52
            throw new \InvalidArgumentException('No MFA provider for identifier ' . $identifier . 'found.', 1610994735);
53
        }
54
55
        return $this->providers[$identifier];
56
    }
57
58
    public function getProviders(): array
59
    {
60
        return $this->providers;
61
    }
62
63
    /**
64
     * Whether the given user has active providers
65
     *
66
     * @param AbstractUserAuthentication $user
67
     * @return bool
68
     */
69
    public function hasActiveProviders(AbstractUserAuthentication $user): bool
70
    {
71
        return $this->getActiveProviders($user) !== [];
72
    }
73
74
    /**
75
     * Get all active providers for the given user
76
     *
77
     * @param AbstractUserAuthentication $user
78
     * @return MfaProviderManifestInterface[]
79
     */
80
    public function getActiveProviders(AbstractUserAuthentication $user): array
81
    {
82
        return array_filter($this->providers, static function ($provider) use ($user) {
83
            return $provider->isActive(MfaProviderPropertyManager::create($provider, $user));
84
        });
85
    }
86
87
    /**
88
     * Get the first provider for the user which can be used for authentication.
89
     * This is either the user specified default provider, or the first active
90
     * provider based on the providers configured ordering.
91
     *
92
     * @param AbstractUserAuthentication $user
93
     * @return MfaProviderManifestInterface
94
     */
95
    public function getFirstAuthenticationAwareProvider(AbstractUserAuthentication $user): ?MfaProviderManifestInterface
96
    {
97
        // Since the user is not fully authenticated we need to unpack UC here to be
98
        // able to retrieve a possible defined default (preferred) provider.
99
        $user->unpack_uc();
100
101
        $activeProviders = $this->getActiveProviders($user);
102
        // If the user did not activate any provider yet, authentication is not possible
103
        if ($activeProviders === []) {
104
            return null;
105
        }
106
        // Check if the user has chosen a default (preferred) provider, which is still active
107
        $defaultProvider = (string)($user->uc['mfa']['defaultProvider'] ?? '');
108
        if ($defaultProvider !== '' && isset($activeProviders[$defaultProvider])) {
109
            return $activeProviders[$defaultProvider];
110
        }
111
        // If no default provider exists or is not valid, return the first active provider
112
        return array_shift($activeProviders);
113
    }
114
115
    /**
116
     * Whether the given user has locked providers
117
     *
118
     * @param AbstractUserAuthentication $user
119
     * @return bool
120
     */
121
    public function hasLockedProviders(AbstractUserAuthentication $user): bool
122
    {
123
        return $this->getLockedProviders($user) !== [];
124
    }
125
126
    /**
127
     * Get all locked providers for the given user
128
     *
129
     * @param AbstractUserAuthentication $user
130
     * @return MfaProviderManifestInterface[]
131
     */
132
    public function getLockedProviders(AbstractUserAuthentication $user): array
133
    {
134
        return array_filter($this->providers, static function ($provider) use ($user) {
135
            return $provider->isLocked(MfaProviderPropertyManager::create($provider, $user));
136
        });
137
    }
138
139
    public function allowedProvidersItemsProcFunc(array &$parameters): void
140
    {
141
        foreach ($this->providers as $provider) {
142
            $parameters['items'][] = [
143
                $provider->getTitle(),
144
                $provider->getIdentifier(),
145
                $provider->getIconIdentifier()
146
            ];
147
        }
148
    }
149
}
150