File: /var/www/payments-gateway/vendor/symfony/maker-bundle/src/Security/InteractiveSecurityHelper.php
<?php
/*
* This file is part of the Symfony MakerBundle package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Bundle\MakerBundle\Security;
use Symfony\Bundle\MakerBundle\Security\Model\Authenticator;
use Symfony\Bundle\MakerBundle\Security\Model\AuthenticatorType;
use Symfony\Bundle\MakerBundle\Str;
use Symfony\Bundle\MakerBundle\Validator;
use Symfony\Component\Console\Style\SymfonyStyle;
use Symfony\Component\Security\Core\User\UserInterface;
/**
* @internal
*/
final class InteractiveSecurityHelper
{
public function guessFirewallName(SymfonyStyle $io, array $securityData, ?string $questionText = null): string
{
$realFirewalls = array_filter(
$securityData['security']['firewalls'] ?? [],
static fn ($item) => !isset($item['security']) || true === $item['security']
);
if (0 === \count($realFirewalls)) {
return 'main';
}
if (1 === \count($realFirewalls)) {
return key($realFirewalls);
}
return $io->choice(
$questionText ?? 'Which firewall do you want to update?',
array_keys($realFirewalls),
key($realFirewalls)
);
}
public function guessUserClass(SymfonyStyle $io, array $providers, ?string $questionText = null): string
{
if (1 === \count($providers) && isset(current($providers)['entity'])) {
$entityProvider = current($providers);
return $entityProvider['entity']['class'];
}
return $io->ask(
$questionText ?? 'Enter the User class that you want to authenticate (e.g. <fg=yellow>App\\Entity\\User</>)',
$this->guessUserClassDefault(),
Validator::classIsUserInterface(...)
);
}
private function guessUserClassDefault(): string
{
if (class_exists('App\\Entity\\User') && isset(class_implements('App\\Entity\\User')[UserInterface::class])) {
return 'App\\Entity\\User';
}
if (class_exists('App\\Security\\User') && isset(class_implements('App\\Security\\User')[UserInterface::class])) {
return 'App\\Security\\User';
}
return '';
}
public function guessUserNameField(SymfonyStyle $io, string $userClass, array $providers): string
{
if (1 === \count($providers) && isset(current($providers)['entity']) && isset(current($providers)['entity']['property'])) {
$entityProvider = current($providers);
return $entityProvider['entity']['property'];
}
if (property_exists($userClass, 'email') && !property_exists($userClass, 'username')) {
return 'email';
}
if (!property_exists($userClass, 'email') && property_exists($userClass, 'username')) {
return 'username';
}
$classProperties = [];
$reflectionClass = new \ReflectionClass($userClass);
foreach ($reflectionClass->getProperties() as $property) {
$classProperties[] = $property->name;
}
if (empty($classProperties)) {
throw new \LogicException(\sprintf('No properties were found in "%s" entity', $userClass));
}
return $io->choice(
\sprintf('Which field on your <fg=yellow>%s</> class will people enter when logging in?', $userClass),
$classProperties,
property_exists($userClass, 'username') ? 'username' : (property_exists($userClass, 'email') ? 'email' : null)
);
}
public function guessEmailField(SymfonyStyle $io, string $userClass): string
{
if (property_exists($userClass, 'email')) {
return 'email';
}
$classProperties = [];
$reflectionClass = new \ReflectionClass($userClass);
foreach ($reflectionClass->getProperties() as $property) {
$classProperties[] = $property->name;
}
return $io->choice(
\sprintf('Which field on your <fg=yellow>%s</> class holds the email address?', $userClass),
$classProperties
);
}
public function guessPasswordField(SymfonyStyle $io, string $userClass): string
{
if (property_exists($userClass, 'password')) {
return 'password';
}
$classProperties = [];
$reflectionClass = new \ReflectionClass($userClass);
foreach ($reflectionClass->getProperties() as $property) {
$classProperties[] = $property->name;
}
return $io->choice(
\sprintf('Which field on your <fg=yellow>%s</> class holds the encoded password?', $userClass),
$classProperties
);
}
public function guessPasswordSetter(SymfonyStyle $io, string $userClass): string
{
if (null === ($methodChoices = $this->methodNameGuesser($userClass, 'setPassword'))) {
return 'setPassword';
}
return $io->choice(
\sprintf('Which method on your <fg=yellow>%s</> class can be used to set the encoded password (e.g. setPassword())?', $userClass),
$methodChoices
);
}
public function guessEmailGetter(SymfonyStyle $io, string $userClass, string $emailPropertyName): string
{
$supposedEmailMethodName = \sprintf('get%s', Str::asCamelCase($emailPropertyName));
if (null === ($methodChoices = $this->methodNameGuesser($userClass, $supposedEmailMethodName))) {
return $supposedEmailMethodName;
}
return $io->choice(
\sprintf('Which method on your <fg=yellow>%s</> class can be used to get the email address (e.g. getEmail())?', $userClass),
$methodChoices
);
}
public function guessIdGetter(SymfonyStyle $io, string $userClass): string
{
if (null === ($methodChoices = $this->methodNameGuesser($userClass, 'getId'))) {
return 'getId';
}
return $io->choice(
\sprintf('Which method on your <fg=yellow>%s</> class can be used to get the unique user identifier (e.g. getId())?', $userClass),
$methodChoices
);
}
/**
* @param array<string, array<string, mixed>> $firewalls Config data from security.firewalls
*
* @return Authenticator[]
*/
public function getAuthenticatorsFromConfig(array $firewalls): array
{
$authenticators = [];
/* Iterate over each firewall that exists e.g. security.firewalls.main
* $firewallName could be "main" or "dev", etc...
* $firewallConfig should be an array of the firewalls params
*/
foreach ($firewalls as $firewallName => $firewallConfig) {
if (!\is_array($firewallConfig)) {
continue;
}
$authenticators = [
...$authenticators,
...$this->getAuthenticatorsFromConfigData($firewallConfig, $firewallName),
];
}
return $authenticators;
}
/**
* Pass in a firewalls config e.g. security.firewalls.main like:
* pattern: ^/path
* form_login:
* login_path: app_login
* custom_authenticator:
* - App\Security\MyAuthenticator
*
* @param array<string, mixed> $firewallConfig
*
* @return Authenticator[]
*/
private function getAuthenticatorsFromConfigData(array $firewallConfig, string $firewallName): array
{
$authenticators = [];
foreach ($firewallConfig as $potentialAuthenticator => $configData) {
// Check if $potentialAuthenticator is a supported authenticator or if its some other key.
if (null === ($authenticator = AuthenticatorType::tryFrom($potentialAuthenticator))) {
// $potentialAuthenticator is probably something like "pattern" or "lazy", not an authenticator
continue;
}
// $potentialAuthenticator is a supported authenticator. Check if it's a custom_authenticator.
if (AuthenticatorType::CUSTOM !== $authenticator) {
// We found a "built in" authenticator - "form_login", "json_login", etc...
$authenticators[] = new Authenticator($authenticator, $firewallName);
continue;
}
/*
* $potentialAuthenticator = custom_authenticator.
* $configData is either [App\MyAuthenticator] or (string) App\MyAuthenticator
*/
$customAuthenticators = $this->getCustomAuthenticators($configData, $firewallName);
$authenticators = [...$authenticators, ...$customAuthenticators];
}
return $authenticators;
}
/**
* @param string|array<string> $customAuthenticators A single entry from custom_authenticators or an array of authenticators
*
* @return Authenticator[]
*/
private function getCustomAuthenticators(string|array $customAuthenticators, string $firewallName): array
{
if (\is_string($customAuthenticators)) {
$customAuthenticators = [$customAuthenticators];
}
$authenticators = [];
foreach ($customAuthenticators as $customAuthenticatorClass) {
$authenticators[] = new Authenticator(AuthenticatorType::CUSTOM, $firewallName, $customAuthenticatorClass);
}
return $authenticators;
}
private function methodNameGuesser(string $className, string $suspectedMethodName): ?array
{
$reflectionClass = new \ReflectionClass($className);
if ($reflectionClass->hasMethod($suspectedMethodName)) {
return null;
}
$classMethods = [];
foreach ($reflectionClass->getMethods() as $method) {
$classMethods[] = $method->name;
}
return $classMethods;
}
}