From dd05888450f6d087648a3f3a43608192e9c19ed5 Mon Sep 17 00:00:00 2001 From: franck Date: Tue, 9 Jul 2013 11:42:25 +0200 Subject: [PATCH] Added Auth loop --- .../Admin/Controller/BaseAdminController.php | 2 +- core/lib/Thelia/Config/Resources/config.xml | 5 +- .../Core/Security/AuthenticationProcessor.php | 35 +++++++ ...ecurityManager.php => SecurityContext.php} | 2 +- .../Security/Token/UsernamePasswordToken.php | 4 +- .../AdminUserProvider.php | 4 +- .../CustomerUserProvider.php | 7 +- .../UserProviderInterface.php | 2 +- .../Thelia/Core/Template/Element/BaseLoop.php | 93 +++++++++++-------- core/lib/Thelia/Core/Template/Loop/Auth.php | 92 ++++++++++++++++++ .../Core/Template/Smarty/Plugins/Security.php | 21 ++--- .../Template/Smarty/Plugins/TheliaLoop.php | 9 +- core/lib/Thelia/Model/Admin.php | 2 +- core/lib/Thelia/Model/Customer.php | 2 +- templates/smarty-sample/index.html | 9 ++ 15 files changed, 220 insertions(+), 69 deletions(-) create mode 100644 core/lib/Thelia/Core/Security/AuthenticationProcessor.php rename core/lib/Thelia/Core/Security/{SecurityManager.php => SecurityContext.php} (99%) rename core/lib/Thelia/Core/Security/{User => UserProvider}/AdminUserProvider.php (65%) rename core/lib/Thelia/Core/Security/{User => UserProvider}/CustomerUserProvider.php (56%) rename core/lib/Thelia/Core/Security/{User => UserProvider}/UserProviderInterface.php (84%) create mode 100644 core/lib/Thelia/Core/Template/Loop/Auth.php diff --git a/core/lib/Thelia/Admin/Controller/BaseAdminController.php b/core/lib/Thelia/Admin/Controller/BaseAdminController.php index 7c66c430b..7dc8f8a15 100755 --- a/core/lib/Thelia/Admin/Controller/BaseAdminController.php +++ b/core/lib/Thelia/Admin/Controller/BaseAdminController.php @@ -134,7 +134,7 @@ class BaseAdminController extends ContainerAware */ public function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH) { - return "thelia2/$route"; + return "thelia2/$route"; //FIXME //return $this->container->get('router')->generate($route, $parameters, $referenceType); } diff --git a/core/lib/Thelia/Config/Resources/config.xml b/core/lib/Thelia/Config/Resources/config.xml index 4aa6cedb3..dee0b57b6 100755 --- a/core/lib/Thelia/Config/Resources/config.xml +++ b/core/lib/Thelia/Config/Resources/config.xml @@ -8,6 +8,7 @@ + @@ -56,7 +57,7 @@ - + @@ -83,6 +84,8 @@ + + %thelia.parser.loops% diff --git a/core/lib/Thelia/Core/Security/AuthenticationProcessor.php b/core/lib/Thelia/Core/Security/AuthenticationProcessor.php new file mode 100644 index 000000000..77fd3bd77 --- /dev/null +++ b/core/lib/Thelia/Core/Security/AuthenticationProcessor.php @@ -0,0 +1,35 @@ +container = $container; + } + + public function createToken(Request $request) { + + $context = $request->get('_context'); + + try { + $securityContext = $this->container->get("security.$context"); + + $token = new UsernamePasswordToken( + $request->get('_username'), + $request->get('_password') + ); + + $securityContext->setToken($token); + } + catch (\Exception $ex) { + // Nothing to do + } + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Security/SecurityManager.php b/core/lib/Thelia/Core/Security/SecurityContext.php similarity index 99% rename from core/lib/Thelia/Core/Security/SecurityManager.php rename to core/lib/Thelia/Core/Security/SecurityContext.php index b60bf14d2..683431518 100644 --- a/core/lib/Thelia/Core/Security/SecurityManager.php +++ b/core/lib/Thelia/Core/Security/SecurityContext.php @@ -31,7 +31,7 @@ use Thelia\Core\Security\Exception\AuthenticationTokenNotFoundException; * * @author Franck Allimant */ -class SecurityManager { +class SecurityContext { /* protected $authProvider; diff --git a/core/lib/Thelia/Core/Security/Token/UsernamePasswordToken.php b/core/lib/Thelia/Core/Security/Token/UsernamePasswordToken.php index f605d1767..03f73dbdd 100644 --- a/core/lib/Thelia/Core/Security/Token/UsernamePasswordToken.php +++ b/core/lib/Thelia/Core/Security/Token/UsernamePasswordToken.php @@ -21,12 +21,12 @@ class UsernamePasswordToken extends AbstractToken * * @throws \InvalidArgumentException */ - public function __construct($username, $password, $authenticated = false) + public function __construct($username, $password, array $roles = array()) { $this->setUser($username); $this->credentials = $password; - parent::setAuthenticated($authenticated); + parent::setAuthenticated(count($roles) > 0); } /** diff --git a/core/lib/Thelia/Core/Security/User/AdminUserProvider.php b/core/lib/Thelia/Core/Security/UserProvider/AdminUserProvider.php similarity index 65% rename from core/lib/Thelia/Core/Security/User/AdminUserProvider.php rename to core/lib/Thelia/Core/Security/UserProvider/AdminUserProvider.php index 9df5ee484..c9ae34a96 100644 --- a/core/lib/Thelia/Core/Security/User/AdminUserProvider.php +++ b/core/lib/Thelia/Core/Security/UserProvider/AdminUserProvider.php @@ -1,7 +1,5 @@ request = $request; + $this->dispatcher = $dispatcher; + $this->securityContext = $securityContext; + + $this->args = $this->getArgDefinitions()->addArguments($this->getDefaultArgs()); } + /** + * Define common loop arguments + * + * @return an array ofL \Thelia\Core\Template\Loop\Argument\Argument + */ + protected function getDefaultArgs() + { + return array( + Argument::createIntTypeArgument('offset', 0), + Argument::createIntTypeArgument('page'), + Argument::createIntTypeArgument('limit', 10), + ); + } + + /** + * Provides a getter to loop parameters + * + * @param string $name the methode name (only getArgname is supported) + * @param mixed $arguments this parameter is ignored + * @throws \InvalidArgumentException if the parameter is unknown or the method name is not supported. + */ public function __call($name, $arguments) { + if (substr($name, 0, 3) == 'get') { $argName = strtolower(substr($name, 3)); @@ -65,22 +100,6 @@ abstract class BaseLoop } throw new \InvalidArgumentException(sprintf("Unsupported magic method %s. only getArgname() is supported.", $name)); - - } - - - /** - * Create a new Loop - * - * @param \Symfony\Component\HttpFoundation\Request $request - * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher - */ - public function __construct(Request $request, EventDispatcherInterface $dispatcher) - { - $this->request = $request; - $this->dispatcher = $dispatcher; - - $this->args = $this->getArgDefinitions()->addArguments($this->getDefaultArgs()); } /** @@ -103,30 +122,26 @@ abstract class BaseLoop if($value === null && $argument->mandatory) { $faultActor[] = $argument->name; $faultDetails[] = sprintf('"%s" parameter is missing', $argument->name); - continue; } - - /* check if empty */ - if($value === '' && !$argument->empty) { + else if($value === '' && !$argument->empty) { + /* check if empty */ $faultActor[] = $argument->name; $faultDetails[] = sprintf('"%s" parameter cannot be empty', $argument->name); - continue; } - - /* check type */ - if($value !== null && !$argument->type->isValid($value)) { + else if($value !== null && !$argument->type->isValid($value)) { + /* check type */ $faultActor[] = $argument->name; $faultDetails[] = sprintf('Invalid value for "%s" argument', $argument->name); - continue; } + else { + /* set default */ + /* did it as last checking for we consider default value is acceptable no matter type or empty restriction */ + if($value === null) { + $value = $argument->default; + } - /* set default */ - /* did it as last checking for we consider default value is acceptable no matter type or empty restriction */ - if($value === null) { - $value = $argument->default; - } - - $argument->setValue($value); + $argument->setValue($value); + } $this->args->next(); } diff --git a/core/lib/Thelia/Core/Template/Loop/Auth.php b/core/lib/Thelia/Core/Template/Loop/Auth.php new file mode 100644 index 000000000..d0c477ef9 --- /dev/null +++ b/core/lib/Thelia/Core/Template/Loop/Auth.php @@ -0,0 +1,92 @@ +. */ +/* */ +/*************************************************************************************/ + +namespace Thelia\Core\Template\Loop; + +use Thelia\Core\Template\Element\BaseLoop; +use Thelia\Core\Template\Element\LoopResult; +use Thelia\Core\Template\Element\LoopResultRow; + +use Thelia\Core\Template\Loop\Argument\ArgumentCollection; +use Thelia\Core\Template\Loop\Argument\Argument; + +use Thelia\Type\TypeCollection; +use Thelia\Type; + +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * + * @package Thelia\Core\Template\Loop + * + * @author Franck Allimant + */ +class Auth extends BaseLoop +{ + public function getArgDefinitions() + { + return new ArgumentCollection( + Argument::createAnyTypeArgument('roles', null, true), + Argument::createAnyTypeArgument('permissions') + ); + } + + private function _explode($commaSeparatedValues) + { + + $array = explode(',', $commaSeparatedValues); + + if (array_walk($array, function(&$item) { + $item = strtoupper(trim($item)); + })) { + return $array; + } + + return array(); + } + + /** + * + * + * @return \Thelia\Core\Template\Element\LoopResult + */ + public function exec(&$pagination) + { + $roles = $this->_explode($this->getRoles()); + $permissions = $this->_explode($this->getPermissions()); + + $loopResult = new LoopResult(); + + try { + $this->securityContext->isGranted($roles, $permissions == null ? array() : $permissions); + + // Create an empty row: loop is no longer empty :) + $loopResult->addRow(new LoopResultRow()); + } + catch (\Exception $ex) { + // Not granted, loop is empty + } + + return $loopResult; + } +} \ No newline at end of file diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/Security.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/Security.php index de7573be6..93367f341 100644 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/Security.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/Security.php @@ -26,15 +26,15 @@ namespace Thelia\Core\Template\Smarty\Plugins; use Thelia\Core\Template\Smarty\SmartyPluginDescriptor; use Thelia\Core\Template\Smarty\SmartyPluginInterface; use Thelia\Core\Template\Smarty\Assets\SmartyAssetsManager; -use Thelia\Core\Security\SecurityManager; +use Thelia\Core\Security\SecurityContext; class Security implements SmartyPluginInterface { - private $securityManager; + private $securityContext; - public function __construct(SecurityManager $securityManager) + public function __construct(SecurityContext $securityContext) { - $this->securityManager = $securityManager; + $this->securityContext = $securityContext; } private function _explode($commaSeparatedValues) @@ -54,17 +54,16 @@ class Security implements SmartyPluginInterface /** * Process security check function * - * @param unknown $params + * @param array $params * @param unknown $smarty - * @return string + * @return string no text is returned. */ - public function checkAUth($params, &$smarty) + public function checkAuthFunction($params, &$smarty) { $roles = $this->_explode($params['role']); - $permissions = $this->_explode($params['role']); - - $this->securityManager->isGranted($roles, $permissions); + $permissions = $this->_explode($params['permissions']); + $this->securityContext->isGranted($roles, $permissions); } /** @@ -75,7 +74,7 @@ class Security implements SmartyPluginInterface public function getPluginDescriptors() { return array( - new SmartyPluginDescriptor('function', 'check_auth', $this, 'checkAUth'), + new SmartyPluginDescriptor('function', 'check_auth', $this, 'checkAuthFunction') ); } } diff --git a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php index 77e38d277..3d5496741 100755 --- a/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php +++ b/core/lib/Thelia/Core/Template/Smarty/Plugins/TheliaLoop.php @@ -32,6 +32,7 @@ use Thelia\Core\Template\Element\Exception\InvalidElementException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Thelia\Core\Security\SecurityContext; class TheliaLoop implements SmartyPluginInterface { @@ -40,16 +41,17 @@ class TheliaLoop implements SmartyPluginInterface protected $loopDefinition = array(); protected $request; - protected $dispatcher; + protected $securityContext; protected $loopstack = array(); protected $varstack = array(); - public function __construct(Request $request, EventDispatcherInterface $dispatcher) + public function __construct(Request $request, EventDispatcherInterface $dispatcher, SecurityContext $securityContext) { $this->request = $request; $this->dispatcher = $dispatcher; + $this->securityContext = $securityContext; } /** @@ -294,7 +296,8 @@ class TheliaLoop implements SmartyPluginInterface $loop = $class->newInstance( $this->request, - $this->dispatcher + $this->dispatcher, + $this->securityContext ); $loop->initializeArgs($smartyParams); diff --git a/core/lib/Thelia/Model/Admin.php b/core/lib/Thelia/Model/Admin.php index 6d3627294..5dd4b9ed4 100644 --- a/core/lib/Thelia/Model/Admin.php +++ b/core/lib/Thelia/Model/Admin.php @@ -36,6 +36,6 @@ class Admin extends BaseAdmin implements UserInterface * {@inheritDoc} */ public function getRoles() { - return array(new Role('USER_ADMIN')); + return array(new Role('ROLE_ADMIN')); } } diff --git a/core/lib/Thelia/Model/Customer.php b/core/lib/Thelia/Model/Customer.php index b9adade3f..eb0cbea8a 100644 --- a/core/lib/Thelia/Model/Customer.php +++ b/core/lib/Thelia/Model/Customer.php @@ -132,6 +132,6 @@ class Customer extends BaseCustomer implements UserInterface * {@inheritDoc} */ public function getRoles() { - return array(new Role('USER_CUSTOMER')); + return array(new Role('ROLE_CUSTOMER')); } } diff --git a/templates/smarty-sample/index.html b/templates/smarty-sample/index.html index c185ae5f8..87efeeb4d 100755 --- a/templates/smarty-sample/index.html +++ b/templates/smarty-sample/index.html @@ -1,5 +1,14 @@ {include file="includes/header.html"}
+ +{loop type="auth" name="auth_test" roles="CUSTOMER"} +

Customer is authentified :-)

+{/loop} + +{elseloop rel="auth_test"} +

Customer is not authentified :-(

+{/elseloop} + An image from asset directory : {images file='assets/img/logo-thelia-34px.png'}{intl l='Thelia, solution e-commerce libre'}{/images}