diff --git a/Command/ArchiveTokenCommand.php b/Command/ArchiveTokenCommand.php index 6f535a9..ebe807f 100644 --- a/Command/ArchiveTokenCommand.php +++ b/Command/ArchiveTokenCommand.php @@ -3,41 +3,26 @@ namespace Yokai\SecurityTokenBundle\Command; use DateTime; -use Symfony\Component\Console\Command\Command; +use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand; use Symfony\Component\Console\Helper\QuestionHelper; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Question\ConfirmationQuestion; -use Symfony\Component\DependencyInjection\ContainerInterface; use Yokai\SecurityTokenBundle\Archive\ArchivistInterface; /** * @author Yann Eugoné */ -class ArchiveTokenCommand extends Command +class ArchiveTokenCommand extends ContainerAwareCommand { - /** - * @var ContainerInterface - */ - private $container; - - /** - * @param ContainerInterface $container - */ - public function __construct(ContainerInterface $container) - { - $this->container = $container; - - parent::__construct('yokai:security-token:archive'); - } - /** * @inheritDoc */ protected function configure() { $this + ->setName('yokai:security-token:archive') ->addOption('purpose', null, InputOption::VALUE_OPTIONAL, 'Filter tokens to archive on purpose.') ->addOption('before', null, InputOption::VALUE_OPTIONAL, 'Filter tokens to archive on created date.') ; @@ -71,7 +56,7 @@ protected function execute(InputInterface $input, OutputInterface $output) } /** @var $archivist ArchivistInterface */ - $archivist = $this->container->get('yokai_security_token.resolved.archivist'); + $archivist = $this->getContainer()->get('yokai_security_token.archivist'); $count = $archivist->archive($purpose, $beforeDate); diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 81a77ea..b22e2cc 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -5,32 +5,25 @@ use Symfony\Component\Config\Definition\Builder\NodeDefinition; use Symfony\Component\Config\Definition\Builder\TreeBuilder; use Symfony\Component\Config\Definition\ConfigurationInterface; +use Yokai\SecurityTokenBundle\Archive\DeleteArchivist; +use Yokai\SecurityTokenBundle\Factory\TokenFactory; +use Yokai\SecurityTokenBundle\InformationGuesser\InformationGuesser; +use Yokai\SecurityTokenBundle\Manager\TokenManager; +use Yokai\SecurityTokenBundle\Manager\UserManager; +use Yokai\SecurityTokenBundle\Repository\TokenRepository; /** * @author Yann Eugoné */ class Configuration implements ConfigurationInterface { - /** - * @var string - */ - private $name; - - /** - * @param string $name - */ - public function __construct($name) - { - $this->name = $name; - } - /** * @inheritdoc */ public function getConfigTreeBuilder() { $builder = new TreeBuilder(); - $root = $builder->root($this->name); + $root = $builder->root('yokai_security_token'); $root ->addDefaultsIfNotSet() @@ -80,16 +73,19 @@ private function getServicesNode() ->addDefaultsIfNotSet() ->children() ->scalarNode('information_guesser') - ->defaultValue('yokai_security_token.information_guesser') + ->defaultValue('yokai_security_token.default_information_guesser') + ->end() + ->scalarNode('token_factory') + ->defaultValue('yokai_security_token.default_token_factory') ->end() - ->scalarNode('factory') - ->defaultValue('yokai_security_token.token_factory') + ->scalarNode('token_repository') + ->defaultValue('yokai_security_token.default_token_repository') ->end() - ->scalarNode('repository') - ->defaultValue('yokai_security_token.token_repository') + ->scalarNode('token_manager') + ->defaultValue('yokai_security_token.default_token_manager') ->end() - ->scalarNode('manager') - ->defaultValue('yokai_security_token.token_manager') + ->scalarNode('user_manager') + ->defaultValue('yokai_security_token.default_user_manager') ->end() ->scalarNode('archivist') ->defaultValue('yokai_security_token.delete_archivist') diff --git a/DependencyInjection/YokaiSecurityTokenExtension.php b/DependencyInjection/YokaiSecurityTokenExtension.php index 9800667..352613d 100644 --- a/DependencyInjection/YokaiSecurityTokenExtension.php +++ b/DependencyInjection/YokaiSecurityTokenExtension.php @@ -2,32 +2,23 @@ namespace Yokai\SecurityTokenBundle\DependencyInjection; -use ReflectionClass; -use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader; +use Yokai\SecurityTokenBundle\Archive\ArchivistInterface; use Yokai\SecurityTokenBundle\DependencyInjection\Factory\TokenConfigurationFactory; +use Yokai\SecurityTokenBundle\Factory\TokenFactoryInterface; +use Yokai\SecurityTokenBundle\InformationGuesser\InformationGuesserInterface; +use Yokai\SecurityTokenBundle\Manager\TokenManagerInterface; +use Yokai\SecurityTokenBundle\Manager\UserManagerInterface; +use Yokai\SecurityTokenBundle\Repository\TokenRepositoryInterface; /** * @author Yann Eugoné */ class YokaiSecurityTokenExtension extends Extension { - /** - * @var string - */ - private $name; - - /** - * @param string $name - */ - public function __construct($name) - { - $this->name = $name; - } - /** * @inheritdoc */ @@ -42,18 +33,6 @@ public function load(array $configs, ContainerBuilder $container) $this->registerAliases($config, $container); } - /** - * @inheritDoc - */ - public function getConfiguration(array $config, ContainerBuilder $container) - { - $configuration = new Configuration($this->name); - $reflection = new ReflectionClass($configuration); - $container->addResource(new FileResource($reflection->getFileName())); - - return $configuration; - } - /** * @param array $config * @param ContainerBuilder $container @@ -72,7 +51,7 @@ private function registerTokens(array $config, ContainerBuilder $container) private function registerAliases(array $config, ContainerBuilder $container) { foreach ($config['services'] as $name => $service) { - $container->setAlias(sprintf('yokai_security_token.resolved.%s', $name), $service); + $container->setAlias(sprintf('yokai_security_token.%s', $name), $service); } } } diff --git a/Entity/Token.php b/Entity/Token.php index 3b01311..21038e1 100644 --- a/Entity/Token.php +++ b/Entity/Token.php @@ -3,7 +3,6 @@ namespace Yokai\SecurityTokenBundle\Entity; use DateTime; -use Symfony\Component\Security\Core\User\UserInterface; /** * @author Yann Eugoné @@ -16,9 +15,14 @@ class Token private $id; /** - * @var UserInterface + * @var string + */ + private $userClass; + + /** + * @var string */ - private $user; + private $userId; /** * @var string @@ -56,15 +60,17 @@ class Token private $usedInformation; /** - * @param UserInterface $user - * @param string $value - * @param string $purpose - * @param string $duration - * @param array $information + * @param string $userClass + * @param string $userId + * @param string $value + * @param string $purpose + * @param string $duration + * @param array $information */ - public function __construct(UserInterface $user, $value, $purpose, $duration, array $information) + public function __construct($userClass, $userId, $value, $purpose, $duration, array $information) { - $this->user = $user; + $this->userClass = $userClass; + $this->userId = $userId; $this->value = $value; $this->purpose = $purpose; $this->createdAt = new DateTime(); @@ -81,11 +87,19 @@ public function getId() } /** - * @return UserInterface + * @return string + */ + public function getUserClass() + { + return $this->userClass; + } + + /** + * @return string */ - public function getUser() + public function getUserId() { - return $this->user; + return $this->userId; } /** diff --git a/Factory/TokenFactory.php b/Factory/TokenFactory.php index 1c7ed16..7e6317a 100644 --- a/Factory/TokenFactory.php +++ b/Factory/TokenFactory.php @@ -2,10 +2,10 @@ namespace Yokai\SecurityTokenBundle\Factory; -use Symfony\Component\Security\Core\User\UserInterface; use Yokai\SecurityTokenBundle\Configuration\TokenConfigurationRegistry; use Yokai\SecurityTokenBundle\Entity\Token; use Yokai\SecurityTokenBundle\InformationGuesser\InformationGuesserInterface; +use Yokai\SecurityTokenBundle\Manager\UserManagerInterface; /** * @author Yann Eugoné @@ -23,24 +23,35 @@ class TokenFactory implements TokenFactoryInterface private $informationGuesser; /** - * @param TokenConfigurationRegistry $registry + * @var UserManagerInterface + */ + private $userManager; + + /** + * @param TokenConfigurationRegistry $registry * @param InformationGuesserInterface $informationGuesser + * @param UserManagerInterface $userManager */ - public function __construct(TokenConfigurationRegistry $registry, InformationGuesserInterface $informationGuesser) - { + public function __construct( + TokenConfigurationRegistry $registry, + InformationGuesserInterface $informationGuesser, + UserManagerInterface $userManager + ) { $this->registry = $registry; $this->informationGuesser = $informationGuesser; + $this->userManager = $userManager; } /** * @inheritdoc */ - public function create(UserInterface $user, $purpose) + public function create($user, $purpose) { $configuration = $this->registry->get($purpose); return new Token( - $user, + $this->userManager->getClass($user), + $this->userManager->getId($user), $configuration->getGenerator()->generate(), $purpose, $configuration->getDuration(), diff --git a/Factory/TokenFactoryInterface.php b/Factory/TokenFactoryInterface.php index 80bbe44..423ad93 100644 --- a/Factory/TokenFactoryInterface.php +++ b/Factory/TokenFactoryInterface.php @@ -2,7 +2,6 @@ namespace Yokai\SecurityTokenBundle\Factory; -use Symfony\Component\Security\Core\User\UserInterface; use Yokai\SecurityTokenBundle\Entity\Token; /** @@ -11,10 +10,10 @@ interface TokenFactoryInterface { /** - * @param UserInterface $user - * @param string $purpose + * @param mixed $user + * @param string $purpose * * @return Token */ - public function create(UserInterface $user, $purpose); + public function create($user, $purpose); } diff --git a/Manager/TokenManager.php b/Manager/TokenManager.php index eed7b22..1f2e9c7 100644 --- a/Manager/TokenManager.php +++ b/Manager/TokenManager.php @@ -3,8 +3,6 @@ namespace Yokai\SecurityTokenBundle\Manager; use DateTime; -use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface; -use Symfony\Component\Security\Core\User\UserInterface; use Yokai\SecurityTokenBundle\Entity\Token; use Yokai\SecurityTokenBundle\Factory\TokenFactoryInterface; use Yokai\SecurityTokenBundle\InformationGuesser\InformationGuesserInterface; @@ -15,11 +13,6 @@ */ class TokenManager implements TokenManagerInterface { - /** - * @var TokenStorageInterface - */ - private $tokenStorage; - /** * @var TokenFactoryInterface */ @@ -36,30 +29,41 @@ class TokenManager implements TokenManagerInterface private $informationGuesser; /** - * @param TokenStorageInterface $tokenStorage + * @var UserManagerInterface + */ + private $userManager; + + /** * @param TokenFactoryInterface $factory * @param TokenRepositoryInterface $repository * @param InformationGuesserInterface $informationGuesser + * @param UserManagerInterface $userManager */ public function __construct( - TokenStorageInterface $tokenStorage, TokenFactoryInterface $factory, TokenRepositoryInterface $repository, - InformationGuesserInterface $informationGuesser + InformationGuesserInterface $informationGuesser, + UserManagerInterface $userManager ) { - $this->tokenStorage = $tokenStorage; $this->factory = $factory; $this->repository = $repository; $this->informationGuesser = $informationGuesser; + $this->userManager = $userManager; } /** * @inheritdoc */ - public function create($purpose, UserInterface $user = null) + public function get($purpose, $value) { - $user = $this->getUser($user); + return $this->repository->get($value, $purpose); + } + /** + * @inheritdoc + */ + public function create($purpose, $user) + { do { $token = $this->factory->create($user, $purpose); } while ($this->repository->exists($token->getValue(), $purpose)); @@ -81,26 +85,10 @@ public function setUsed(Token $token, DateTime $at = null) } /** - * @param UserInterface|null $user - * - * @return UserInterface + * @inheritdoc */ - private function getUser(UserInterface $user = null) + public function getUser(Token $token) { - if ($user instanceof UserInterface) { - return $user; - } - - $token = $this->tokenStorage->getToken(); - if (!$token) { - throw new \RuntimeException();//todo - } - - $user = $token->getUser(); - if (!$user instanceof UserInterface) { - throw new \RuntimeException();//todo - } - - return $user; + return $this->userManager->get($token->getUserClass(), $token->getUserId()); } } diff --git a/Manager/TokenManagerInterface.php b/Manager/TokenManagerInterface.php index 09983b2..19875e0 100644 --- a/Manager/TokenManagerInterface.php +++ b/Manager/TokenManagerInterface.php @@ -3,7 +3,6 @@ namespace Yokai\SecurityTokenBundle\Manager; use DateTime; -use Symfony\Component\Security\Core\User\UserInterface; use Yokai\SecurityTokenBundle\Entity\Token; /** @@ -12,16 +11,31 @@ interface TokenManagerInterface { /** - * @param string $purpose - * @param UserInterface $user + * @param string $purpose + * @param string $value * * @return Token */ - public function create($purpose, UserInterface $user = null); + public function get($purpose, $value); + + /** + * @param string $purpose + * @param mixed $user + * + * @return Token + */ + public function create($purpose, $user); /** * @param Token $token * @param DateTime|null $at */ public function setUsed(Token $token, DateTime $at = null); + + /** + * @param Token $token + * + * @return mixed + */ + public function getUser(Token $token); } diff --git a/Manager/UserManager.php b/Manager/UserManager.php new file mode 100644 index 0000000..7902348 --- /dev/null +++ b/Manager/UserManager.php @@ -0,0 +1,52 @@ +entityManager = $entityManager; + } + + /** + * @inheritDoc + */ + public function get($class, $id) + { + return $this->entityManager->find($class, $id); + } + + /** + * @inheritDoc + */ + public function getClass($user) + { + return ClassUtils::getClass($user); + } + + /** + * @inheritDoc + */ + public function getId($user) + { + $identifiers = $this->entityManager->getClassMetadata(ClassUtils::getClass($user))->getIdentifierValues($user); + + if (count($identifiers) > 1) { + throw new \RuntimeException('Entities with composite ids are not supported'); + } + + return (string) reset($identifiers); + } +} diff --git a/Manager/UserManagerInterface.php b/Manager/UserManagerInterface.php new file mode 100644 index 0000000..3f8109c --- /dev/null +++ b/Manager/UserManagerInterface.php @@ -0,0 +1,28 @@ +getUserRepository()->findOneByUsername($request->request->get('username')); if (!$user) { - return /* up to you */; + throw $this->createNotFoundException(); // or whatever you want } $this->getTokenManager()->create('reset_password', $user); - return /* up to you */; + return new Response(); // or whatever you want } public function doResetPasswordAction(Request $request) @@ -102,17 +97,17 @@ class SecurityController extends Controller } if (!$token) { - return /* up to you */; + throw $this->createNotFoundException(); // or whatever you want } - $user = $token->getUser(); - $user->setPassword($request->request->get('password')); + $user = $this->getTokenManager()->getUser($token); + $user->setPassword($request->request->get('password')); $this->getUserManager()->flush($user); $this->getTokenManager()->setUsed($token); - return /* up to you */; + return new Response(); // or whatever you want } /** @@ -120,15 +115,7 @@ class SecurityController extends Controller */ private function getTokenManager() { - return $this->get('yokai_security_token.resolved.manager'); - } - - /** - * @return TokenRepositoryInterface - */ - private function getTokenRepository() - { - return $this->get('yokai_security_token.resolved.repository'); + return $this->get('yokai_security_token.token_manager'); } /** @@ -136,7 +123,7 @@ class SecurityController extends Controller */ private function getUserRepository() { - return /* up to you */; + return $this->getDoctrine()->getRepository('AppBundle:User'); } /** @@ -144,7 +131,7 @@ class SecurityController extends Controller */ private function getUserManager() { - return /* up to you */; + return $this->getDoctrine()->getManager(); } } ``` @@ -157,7 +144,7 @@ according to what you have configured for the purpose you asked. **doResetPasswordAction** : -The `Token Repository` service will handle retrieving security token for you, +The `Token Manager` service will handle retrieving security token for you, returning it when succeed, and throwing exceptions if something wrong : - Token not found diff --git a/Repository/TokenRepository.php b/Repository/TokenRepository.php index b5dfba9..a69e050 100644 --- a/Repository/TokenRepository.php +++ b/Repository/TokenRepository.php @@ -4,7 +4,6 @@ use Doctrine\ORM\EntityRepository; use Yokai\SecurityTokenBundle\Entity\Token; -use Yokai\SecurityTokenBundle\Exception\InvalidTokenException; use Yokai\SecurityTokenBundle\Exception\TokenExpiredException; use Yokai\SecurityTokenBundle\Exception\TokenNotFoundException; use Yokai\SecurityTokenBundle\Exception\TokenUsedException; diff --git a/Resources/config/doctrine/Token.orm.xml b/Resources/config/doctrine/Token.orm.xml index 5a60210..c65ca1f 100644 --- a/Resources/config/doctrine/Token.orm.xml +++ b/Resources/config/doctrine/Token.orm.xml @@ -6,21 +6,30 @@ + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + diff --git a/Resources/config/services.xml b/Resources/config/services.xml index f073815..ea26936 100644 --- a/Resources/config/services.xml +++ b/Resources/config/services.xml @@ -12,7 +12,7 @@ - @@ -23,36 +23,36 @@ class="Yokai\SecurityTokenBundle\Generator\OpenSslTokenGenerator" public="false"/> - - - + + - - - - - + + + + - - + + - - - + + diff --git a/YokaiSecurityTokenBundle.php b/YokaiSecurityTokenBundle.php index 28994f3..be134e7 100644 --- a/YokaiSecurityTokenBundle.php +++ b/YokaiSecurityTokenBundle.php @@ -2,11 +2,9 @@ namespace Yokai\SecurityTokenBundle; -use Symfony\Component\Console\Application; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; use Yokai\DependencyInjection\CompilerPass\ArgumentRegisterTaggedServicesCompilerPass; -use Yokai\SecurityTokenBundle\DependencyInjection\YokaiSecurityTokenExtension; /** * @author Yann Eugoné @@ -29,35 +27,4 @@ public function build(ContainerBuilder $container) ) ; } - - /** - * @inheritDoc - */ - public function getContainerExtension() - { - return new YokaiSecurityTokenExtension('yokai_security_token'); - } - - /** - * @inheritDoc - */ - public function getNamespace() - { - return __NAMESPACE__; - } - - /** - * @inheritDoc - */ - public function getPath() - { - return __DIR__; - } - - /** - * @inheritDoc - */ - public function registerCommands(Application $application) - { - } } diff --git a/composer.json b/composer.json index bbb9c48..e9de7ed 100644 --- a/composer.json +++ b/composer.json @@ -9,8 +9,10 @@ } ], "require": { - "php": ">=5.5.9", + "php": ">=7.0", "symfony/framework-bundle": "~2.7|~3.0", + "doctrine/orm": "^2.5", + "doctrine/doctrine-bundle": "^1.6", "yokai/dependency-injection": "~1.0" }, "require-dev": { @@ -21,7 +23,7 @@ "minimum-stability": "stable", "extra": { "branch-alias": { - "dev-master": "1.0-dev" + "dev-master": "2.0-dev" } } }