/
home
/
obinna
/
html
/
boaz2
/
vendor
/
symfony
/
maker-bundle
/
src
/
Security
/
Upload File
HOME
<?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\Util\YamlSourceManipulator; use Symfony\Component\HttpKernel\Log\Logger; use Symfony\Component\PasswordHasher\Hasher\NativePasswordHasher; use Symfony\Component\Security\Core\Encoder\NativePasswordEncoder; /** * @author Ryan Weaver <ryan@symfonycasts.com> * @author Jesse Rushlow <jr@rushlow.dev> * * @internal */ final class SecurityConfigUpdater { /** @var YamlSourceManipulator */ private $manipulator; /** @var Logger|null */ private $ysmLogger; public function __construct(Logger $ysmLogger = null) { $this->ysmLogger = $ysmLogger; } /** * Updates security.yaml contents based on a new User class. */ public function updateForUserClass(string $yamlSource, UserClassConfiguration $userConfig, string $userClass): string { $this->manipulator = new YamlSourceManipulator($yamlSource); if (null !== $this->ysmLogger) { $this->manipulator->setLogger($this->ysmLogger); } $this->normalizeSecurityYamlFile(); $this->updateProviders($userConfig, $userClass); if ($userConfig->hasPassword()) { $symfonyGte53 = class_exists(NativePasswordHasher::class); $this->updatePasswordHashers($userConfig, $userClass, $symfonyGte53 ? 'password_hashers' : 'encoders'); } $contents = $this->manipulator->getContents(); $this->manipulator = null; return $contents; } public function updateForAuthenticator(string $yamlSource, string $firewallName, $chosenEntryPoint, string $authenticatorClass, bool $logoutSetup, bool $useSecurity52): string { $this->manipulator = new YamlSourceManipulator($yamlSource); if (null !== $this->ysmLogger) { $this->manipulator->setLogger($this->ysmLogger); } $this->normalizeSecurityYamlFile(); $newData = $this->manipulator->getData(); if (!isset($newData['security']['firewalls'])) { if ($newData['security']) { $newData['security']['_firewalls'] = $this->manipulator->createEmptyLine(); } $newData['security']['firewalls'] = []; } if (!isset($newData['security']['firewalls'][$firewallName])) { if ($useSecurity52) { $newData['security']['firewalls'][$firewallName] = ['lazy' => true]; } else { $newData['security']['firewalls'][$firewallName] = ['anonymous' => 'lazy']; } } $firewall = $newData['security']['firewalls'][$firewallName]; if ($useSecurity52) { if (isset($firewall['custom_authenticator'])) { if (\is_array($firewall['custom_authenticator'])) { $firewall['custom_authenticator'][] = $authenticatorClass; } else { $stringValue = $firewall['custom_authenticator']; $firewall['custom_authenticator'] = []; $firewall['custom_authenticator'][] = $stringValue; $firewall['custom_authenticator'][] = $authenticatorClass; } } else { $firewall['custom_authenticator'] = $authenticatorClass; } if (!isset($firewall['entry_point']) && $chosenEntryPoint) { $firewall['entry_point_empty_line'] = $this->manipulator->createEmptyLine(); $firewall['entry_point_comment'] = $this->manipulator->createCommentLine( ' the entry_point start() method determines what happens when an anonymous user accesses a protected page' ); $firewall['entry_point'] = $authenticatorClass; } } else { if (!isset($firewall['guard'])) { $firewall['guard'] = []; } if (!isset($firewall['guard']['authenticators'])) { $firewall['guard']['authenticators'] = []; } $firewall['guard']['authenticators'][] = $authenticatorClass; if (\count($firewall['guard']['authenticators']) > 1) { $firewall['guard']['entry_point'] = $chosenEntryPoint ?? current($firewall['guard']['authenticators']); } } if (!isset($firewall['logout']) && $logoutSetup) { $firewall['logout'] = ['path' => 'app_logout']; $firewall['logout'][] = $this->manipulator->createCommentLine( ' where to redirect after logout' ); $firewall['logout'][] = $this->manipulator->createCommentLine( ' target: app_any_route' ); } $newData['security']['firewalls'][$firewallName] = $firewall; $this->manipulator->setData($newData); return $this->manipulator->getContents(); } private function normalizeSecurityYamlFile(): void { if (!isset($this->manipulator->getData()['security'])) { $newData = $this->manipulator->getData(); $newData['security'] = []; $this->manipulator->setData($newData); } } private function updateProviders(UserClassConfiguration $userConfig, string $userClass): void { $this->removeMemoryProviderIfIsSingleConfigured(); $newData = $this->manipulator->getData(); if ($newData['security'] && !\array_key_exists('providers', $newData['security'])) { $newData['security']['_providers'] = $this->manipulator->createEmptyLine(); } $newData['security']['providers']['__'] = $this->manipulator->createCommentLine( ' used to reload user from session & other features (e.g. switch_user)' ); if ($userConfig->isEntity()) { $newData['security']['providers']['app_user_provider'] = [ 'entity' => [ 'class' => $userClass, 'property' => $userConfig->getIdentityPropertyName(), ], ]; } else { if (!$userConfig->getUserProviderClass()) { throw new \LogicException('User provider class must be set for non-entity user.'); } $newData['security']['providers']['app_user_provider'] = [ 'id' => $userConfig->getUserProviderClass(), ]; } $this->manipulator->setData($newData); } private function updatePasswordHashers(UserClassConfiguration $userConfig, string $userClass, string $keyName = 'password_hashers'): void { $newData = $this->manipulator->getData(); if ('password_hashers' === $keyName && isset($newData['security']['encoders'])) { // fallback to "encoders" if the user already defined encoder config $this->updatePasswordHashers($userConfig, $userClass, 'encoders'); return; } if (!isset($newData['security'][$keyName])) { // by convention, password_hashers are put before the user provider option $providersIndex = array_search('providers', array_keys($newData['security'])); if (false === $providersIndex) { $newData['security'] = [$keyName => []] + $newData['security']; } else { $newData['security'] = array_merge( \array_slice($newData['security'], 0, $providersIndex), [$keyName => []], \array_slice($newData['security'], $providersIndex) ); } } $newData['security'][$keyName][$userClass] = [ 'algorithm' => $userConfig->shouldUseArgon2() ? 'argon2i' : ((class_exists(NativePasswordHasher::class) || class_exists(NativePasswordEncoder::class)) ? 'auto' : 'bcrypt'), ]; $newData['security'][$keyName]['_'] = $this->manipulator->createEmptyLine(); $this->manipulator->setData($newData); } private function removeMemoryProviderIfIsSingleConfigured(): void { if (!$this->isSingleInMemoryProviderConfigured()) { return; } $newData = $this->manipulator->getData(); $memoryProviderName = array_keys($newData['security']['providers'])[0]; $newData['security']['providers'] = []; foreach ($newData['security']['firewalls'] as &$firewall) { if (($firewall['provider'] ?? null) === $memoryProviderName) { $firewall['provider'] = 'app_user_provider'; } } $this->manipulator->setData($newData); } private function isSingleInMemoryProviderConfigured(): bool { if (!isset($this->manipulator->getData()['security']['providers'])) { return false; } $providersConfig = $this->manipulator->getData()['security']['providers']; if (1 !== \count($providersConfig)) { return false; } $firstProviderConfig = array_values($providersConfig)[0]; return \array_key_exists('memory', $firstProviderConfig); } }