Finalized admin security
This commit is contained in:
@@ -27,11 +27,13 @@ use Symfony\Component\DependencyInjection\ContainerAware;
|
|||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
|
||||||
use Thelia\Form\BaseForm;
|
use Thelia\Form\BaseForm;
|
||||||
use Thelia\Model\ConfigQuery;
|
|
||||||
use Symfony\Component\HttpFoundation\RedirectResponse;
|
use Symfony\Component\HttpFoundation\RedirectResponse;
|
||||||
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
use Symfony\Component\HttpKernel\HttpKernelInterface;
|
||||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||||
use Thelia\Core\Security\Exception\AuthenticationTokenNotFoundException;
|
use Thelia\Core\Security\Exception\AuthenticationTokenNotFoundException;
|
||||||
|
use Thelia\Model\ConfigQuery;
|
||||||
|
use Thelia\Core\Security\Exception\AuthenticationException;
|
||||||
|
use Thelia\Core\Security\SecurityContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -44,14 +46,14 @@ use Thelia\Core\Security\Exception\AuthenticationTokenNotFoundException;
|
|||||||
|
|
||||||
class BaseAdminController extends ContainerAware
|
class BaseAdminController extends ContainerAware
|
||||||
{
|
{
|
||||||
|
|
||||||
const TEMPLATE_404 = "404.html";
|
const TEMPLATE_404 = "404.html";
|
||||||
|
|
||||||
public function notFoundAction()
|
protected function undefinedAction()
|
||||||
{
|
{
|
||||||
return new Response($this->renderRaw(self::TEMPLATE_404), 404);
|
return new Response($this->renderRaw(self::TEMPLATE_404), 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the givent template, and returns the result as an Http Response.
|
* Render the givent template, and returns the result as an Http Response.
|
||||||
*
|
*
|
||||||
@@ -59,7 +61,7 @@ class BaseAdminController extends ContainerAware
|
|||||||
* @param array $args the template arguments
|
* @param array $args the template arguments
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
*/
|
*/
|
||||||
public function render($templateName, $args = array())
|
protected function render($templateName, $args = array())
|
||||||
{
|
{
|
||||||
$response = new Response();
|
$response = new Response();
|
||||||
|
|
||||||
@@ -67,46 +69,78 @@ class BaseAdminController extends ContainerAware
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render the givent template, and returns the result as a string.
|
* Render the given template, and returns the result as a string.
|
||||||
*
|
*
|
||||||
* @param $templateName the complete template name, with extension
|
* @param $templateName the complete template name, with extension
|
||||||
* @param array $args the template arguments
|
* @param array $args the template arguments
|
||||||
* @return \Symfony\Component\HttpFoundation\Response
|
* @return \Symfony\Component\HttpFoundation\Response
|
||||||
*/
|
*/
|
||||||
public function renderRaw($templateName, $args = array())
|
protected function renderRaw($templateName, $args = array())
|
||||||
{
|
{
|
||||||
$args = array_merge($args, array('lang' => 'fr')); // FIXME
|
$session = $this->getSession();
|
||||||
|
|
||||||
|
$args = array_merge($args, array(
|
||||||
|
'locale' => $session->getLocale(),
|
||||||
|
'lang' => $session->getLang()
|
||||||
|
));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$data = $this->getParser()->render($templateName, $args);
|
$data = $this->getParser()->render($templateName, $args);
|
||||||
}
|
|
||||||
catch (AuthenticationTokenNotFoundException $ex) {
|
|
||||||
|
|
||||||
// No auth token -> perform login
|
return $data;
|
||||||
return new RedirectResponse($this->generateUrl('admin/login'));
|
|
||||||
}
|
}
|
||||||
|
catch (AuthenticationException $ex) {
|
||||||
|
|
||||||
return $data;
|
// User is not authenticated, and templates requires authentication -> redirect to login page
|
||||||
|
// (see Thelia\Core\Template\Smarty\Plugins\Security)
|
||||||
|
return new RedirectResponse($this->generateUrl('admin/login')); // FIXME shoud be a parameter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the security context, by default in admin mode.
|
||||||
|
*
|
||||||
|
* @return Thelia\Core\Security\SecurityContext
|
||||||
|
*/
|
||||||
|
protected function getSecurityContext($context = false)
|
||||||
|
{
|
||||||
|
$securityContext = $this->container->get('thelia.securityContext');
|
||||||
|
|
||||||
|
$securityContext->setContext($context === false ? SecurityContext::CONTEXT_BACK_OFFICE : $context);
|
||||||
|
|
||||||
|
return $securityContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return \Symfony\Component\HttpFoundation\Request
|
* @return \Symfony\Component\HttpFoundation\Request
|
||||||
*/
|
*/
|
||||||
public function getRequest()
|
protected function getRequest()
|
||||||
{
|
{
|
||||||
return $this->container->get('request');
|
return $this->container->get('request');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the session from the current request
|
||||||
|
*
|
||||||
|
* @return Ambigous <NULL, \Symfony\Component\HttpFoundation\Session\SessionInterface>
|
||||||
|
*/
|
||||||
|
protected function getSession() {
|
||||||
|
|
||||||
|
$request = $this->getRequest();
|
||||||
|
|
||||||
|
return $request->getSession();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return a ParserInterface instance parser, as configured.
|
* @return a ParserInterface instance parser, as configured.
|
||||||
*/
|
*/
|
||||||
public function getParser()
|
protected function getParser()
|
||||||
{
|
{
|
||||||
$parser = $this->container->get("thelia.parser");
|
$parser = $this->container->get("thelia.parser");
|
||||||
|
|
||||||
// FIXME: should be read from config
|
// Define the template thant shoud be used
|
||||||
$parser->setTemplate('admin/default');
|
$parser->setTemplate(ConfigQuery::read('base_admin_template', 'admin/default'));
|
||||||
|
|
||||||
return $parser;
|
return $parser;
|
||||||
}
|
}
|
||||||
@@ -132,11 +166,19 @@ class BaseAdminController extends ContainerAware
|
|||||||
*
|
*
|
||||||
* @see UrlGeneratorInterface
|
* @see UrlGeneratorInterface
|
||||||
*/
|
*/
|
||||||
public function generateUrl($route, $parameters = array(), $referenceType = UrlGeneratorInterface::ABSOLUTE_PATH)
|
protected function generateUrl($path, array $parameters = array())
|
||||||
{
|
{
|
||||||
return "thelia2/$route"; //FIXME
|
$base = ConfigQuery::read("base_url", "/").$path; //FIXME
|
||||||
|
|
||||||
//return $this->container->get('router')->generate($route, $parameters, $referenceType);
|
$queryString = '';
|
||||||
|
|
||||||
|
foreach($parameters as $name => $value) {
|
||||||
|
$queryString = sprintf("%s=%s&", urlencode($name), urlencode($value));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ('' !== $queryString = rtrim($queryString, "&")) $queryString = '?' . $queryString;
|
||||||
|
|
||||||
|
return $base . $queryString;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,7 +190,7 @@ class BaseAdminController extends ContainerAware
|
|||||||
*
|
*
|
||||||
* @return Response A Response instance
|
* @return Response A Response instance
|
||||||
*/
|
*/
|
||||||
public function forward($controller, array $path = array(), array $query = array())
|
protected function forward($controller, array $path = array(), array $query = array())
|
||||||
{
|
{
|
||||||
$path['_controller'] = $controller;
|
$path['_controller'] = $controller;
|
||||||
$subRequest = $this->container->get('request')->duplicate($query, null, $path);
|
$subRequest = $this->container->get('request')->duplicate($query, null, $path);
|
||||||
@@ -164,7 +206,7 @@ class BaseAdminController extends ContainerAware
|
|||||||
*
|
*
|
||||||
* @return RedirectResponse
|
* @return RedirectResponse
|
||||||
*/
|
*/
|
||||||
public function redirect($url, $status = 302)
|
protected function redirect($url, $status = 302)
|
||||||
{
|
{
|
||||||
return new RedirectResponse($url, $status);
|
return new RedirectResponse($url, $status);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,33 +25,66 @@ namespace Thelia\Admin\Controller;
|
|||||||
|
|
||||||
use Symfony\Component\HttpFoundation\Response;
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
use Thelia\Form\AdminLogin;
|
use Thelia\Form\AdminLogin;
|
||||||
|
use Thelia\Core\Security\Token\UsernamePasswordToken;
|
||||||
|
use Thelia\Core\Security\Authentication\UsernamePasswordAuthenticator;
|
||||||
|
use Thelia\Core\Security\Encoder\PasswordPhpCompatEncoder;
|
||||||
|
use Thelia\Core\Security\Token\TokenInterface;
|
||||||
|
use Thelia\Core\Security\Authentication\AdminUsernamePasswordFormAuthenticator;
|
||||||
|
use Thelia\Model\AdminLog;
|
||||||
|
use Thelia\Core\Security\Exception\AuthenticationException;
|
||||||
|
|
||||||
class SessionController extends BaseAdminController {
|
class SessionController extends BaseAdminController {
|
||||||
|
|
||||||
public function loginAction()
|
public function showLoginAction()
|
||||||
|
{
|
||||||
|
$form = $this->getLoginForm();
|
||||||
|
|
||||||
|
return $this->render("login.html", array(
|
||||||
|
"form" => $form->createView()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkLogoutAction()
|
||||||
|
{
|
||||||
|
$this->getSecurityContext()->clear();
|
||||||
|
|
||||||
|
// Go back to login page.
|
||||||
|
return $this->redirect($this->generateUrl('admin/login'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function checkLoginAction()
|
||||||
{
|
{
|
||||||
$form = $this->getLoginForm();
|
$form = $this->getLoginForm();
|
||||||
|
|
||||||
$request = $this->getRequest();
|
$request = $this->getRequest();
|
||||||
|
|
||||||
if($request->isMethod("POST")) {
|
$authenticator = new AdminUsernamePasswordFormAuthenticator($request, $form);
|
||||||
|
|
||||||
$form->bind($request);
|
try {
|
||||||
|
$user = $authenticator->getAuthentifiedUser();
|
||||||
|
|
||||||
if ($form->isValid()) {
|
// Success -> store user in security context
|
||||||
|
$this->getSecurityContext()->setUser($user);
|
||||||
|
|
||||||
$this->container->get('request')->authenticate(
|
// Log authentication success
|
||||||
$form->get('username')->getData(),
|
AdminLog::append("Authentication successufull", $request, $user);
|
||||||
$form->get('password')->getData()
|
|
||||||
);
|
|
||||||
|
|
||||||
echo "valid"; exit;
|
// Redirect to home page - FIXME: requested URL, if we come from another page ?
|
||||||
}
|
return $this->redirect($this->generateUrl('admin'));
|
||||||
}
|
}
|
||||||
|
catch (AuthenticationException $ex) {
|
||||||
|
|
||||||
return $this->render("login.html", array(
|
// Log authentication failure
|
||||||
"form" => $form->createView()
|
AdminLog::append(sprintf("Authentication failure for username '%s'", $authenticator->getUsername()), $request);
|
||||||
));
|
|
||||||
|
$message = "Login failed. Please check your username and password.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Display the login form again
|
||||||
|
return $this->render("login.html", array(
|
||||||
|
"form" => $authenticator->getLoginForm()->createView(),
|
||||||
|
"message" => $message
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getLoginForm()
|
protected function getLoginForm()
|
||||||
|
|||||||
@@ -11,11 +11,13 @@
|
|||||||
<parameter key="deleteArticle">Thelia\Core\Event\CartEvent</parameter>
|
<parameter key="deleteArticle">Thelia\Core\Event\CartEvent</parameter>
|
||||||
</parameter>
|
</parameter>
|
||||||
</parameters>
|
</parameters>
|
||||||
|
|
||||||
<services>
|
<services>
|
||||||
|
|
||||||
<service id="thelia.action.cart" class="Thelia\Action\Cart">
|
<service id="thelia.action.cart" class="Thelia\Action\Cart">
|
||||||
<tag name="kernel.event_subscriber"/>
|
<tag name="kernel.event_subscriber"/>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="thelia.action.customer" class="Thelia\Action\Customer">
|
<service id="thelia.action.customer" class="Thelia\Action\Customer">
|
||||||
<tag name="kernel.event_subscriber"/>
|
<tag name="kernel.event_subscriber"/>
|
||||||
</service>
|
</service>
|
||||||
|
|||||||
@@ -49,15 +49,23 @@
|
|||||||
<!--
|
<!--
|
||||||
A ControllerResolver that supports "a:b:c", "service:method" and class::method" notations,
|
A ControllerResolver that supports "a:b:c", "service:method" and class::method" notations,
|
||||||
thus allowing the definition of controllers as service (see http://symfony.com/fr/doc/current/cookbook/controller/service.html)
|
thus allowing the definition of controllers as service (see http://symfony.com/fr/doc/current/cookbook/controller/service.html)
|
||||||
We use it here to inject the servi ce container in the admin base controller.
|
We use it here to inject the service container in the admin base controller.
|
||||||
-->
|
-->
|
||||||
<service id="controller_resolver" class="Thelia\Core\Controller\ControllerResolver">
|
<service id="controller_resolver" class="Thelia\Core\Controller\ControllerResolver">
|
||||||
<argument type="service" id="service_container"/>
|
<argument type="service" id="service_container"/>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<!-- Security -->
|
<!-- Translation and internationalisation -->
|
||||||
|
|
||||||
<service id="thelia.security" class="Thelia\Core\Security\SecurityContext" />
|
<service id="thelia.translator" class="Thelia\Core\Translation\Translator">
|
||||||
|
<argument type="string" id="en_US"></argument>
|
||||||
|
</service>
|
||||||
|
|
||||||
|
<!-- Security context for front and back office -->
|
||||||
|
|
||||||
|
<service id="thelia.securityContext" class="Thelia\Core\Security\SecurityContext" scope="request">
|
||||||
|
<argument type="service" id="request" />
|
||||||
|
</service>
|
||||||
|
|
||||||
<!-- Parser configuration -->
|
<!-- Parser configuration -->
|
||||||
|
|
||||||
@@ -84,7 +92,7 @@
|
|||||||
|
|
||||||
<argument type="service" id="request" />
|
<argument type="service" id="request" />
|
||||||
<argument type="service" id="event_dispatcher"/>
|
<argument type="service" id="event_dispatcher"/>
|
||||||
<argument type="service" id="thelia.security"/>
|
<argument type="service" id="thelia.securityContext"/>
|
||||||
|
|
||||||
<call method="setLoopList">
|
<call method="setLoopList">
|
||||||
<argument>%thelia.parser.loops%</argument>
|
<argument>%thelia.parser.loops%</argument>
|
||||||
@@ -102,15 +110,16 @@
|
|||||||
|
|
||||||
<service id="smarty.plugin.translation" class="Thelia\Core\Template\Smarty\Plugins\Translation" >
|
<service id="smarty.plugin.translation" class="Thelia\Core\Template\Smarty\Plugins\Translation" >
|
||||||
<tag name="thelia.parser.register_plugin"/>
|
<tag name="thelia.parser.register_plugin"/>
|
||||||
|
<argument type="service" id="thelia.translator" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="smarty.plugin.module" class="Thelia\Core\Template\Smarty\Plugins\Module" >
|
<service id="smarty.plugin.module" class="Thelia\Core\Template\Smarty\Plugins\Module" >
|
||||||
<tag name="thelia.parser.register_plugin"/>
|
<tag name="thelia.parser.register_plugin"/>
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="smarty.plugin.security" class="Thelia\Core\Template\Smarty\Plugins\Security" >
|
<service id="smarty.plugin.security" class="Thelia\Core\Template\Smarty\Plugins\Security" scope="request">
|
||||||
<tag name="thelia.parser.register_plugin"/>
|
<tag name="thelia.parser.register_plugin"/>
|
||||||
<argument type="service" id="thelia.security" />
|
<argument type="service" id="thelia.securityContext" />
|
||||||
</service>
|
</service>
|
||||||
|
|
||||||
<service id="http_kernel" class="Thelia\Core\TheliaHttpKernel">
|
<service id="http_kernel" class="Thelia\Core\TheliaHttpKernel">
|
||||||
|
|||||||
@@ -4,14 +4,28 @@
|
|||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd">
|
||||||
|
|
||||||
|
<!-- Route to administration base -->
|
||||||
<route id="admin" path="/admin">
|
<route id="admin" path="/admin">
|
||||||
<default key="_controller">Thelia\Admin\Controller\AdminController::indexAction</default>
|
<default key="_controller">Thelia\Admin\Controller\AdminController::indexAction</default>
|
||||||
</route>
|
</route>
|
||||||
|
|
||||||
|
<!-- Route to the administration login page -->
|
||||||
<route id="admin.login" path="/admin/login">
|
<route id="admin.login" path="/admin/login">
|
||||||
<default key="_controller">Thelia\Admin\Controller\SessionController::loginAction</default>
|
<default key="_controller">Thelia\Admin\Controller\SessionController::showLoginAction</default>
|
||||||
</route>
|
</route>
|
||||||
<route id="admin.notfound" path="/admin/{everything}">
|
|
||||||
<default key="_controller">Thelia\Admin\Controller\AdminController::notFoundAction</default>
|
<!-- Route to the administration logout page -->
|
||||||
|
<route id="admin.logout" path="/admin/logout">
|
||||||
|
<default key="_controller">Thelia\Admin\Controller\SessionController::checkLogoutAction</default>
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<!-- Route to the login check controller -->
|
||||||
|
<route id="admin.checklogin" path="/admin/checklogin">
|
||||||
|
<default key="_controller">Thelia\Admin\Controller\SessionController::checkLoginAction</default>
|
||||||
|
</route>
|
||||||
|
|
||||||
|
<route id="admin.undefined" path="/admin/{everything}">
|
||||||
|
<default key="_controller">Thelia\Admin\Controller\AdminController::undefinedAction</default>
|
||||||
<requirement key="everything">.*</requirement>
|
<requirement key="everything">.*</requirement>
|
||||||
</route>
|
</route>
|
||||||
</routes>
|
</routes>
|
||||||
@@ -24,6 +24,7 @@
|
|||||||
namespace Thelia\Core\HttpFoundation\Session;
|
namespace Thelia\Core\HttpFoundation\Session;
|
||||||
|
|
||||||
use Symfony\Component\HttpFoundation\Session\Session as BaseSession;
|
use Symfony\Component\HttpFoundation\Session\Session as BaseSession;
|
||||||
|
use Thelia\Core\Security\User\UserInterface;
|
||||||
|
|
||||||
class Session extends BaseSession {
|
class Session extends BaseSession {
|
||||||
|
|
||||||
@@ -35,7 +36,31 @@ class Session extends BaseSession {
|
|||||||
|
|
||||||
public function getLang()
|
public function getLang()
|
||||||
{
|
{
|
||||||
return $this->get("lang", "en");
|
return substr($this->getLocale(), 0, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function setCustomerUser(UserInterface $user) {
|
||||||
|
$this->set('customer_user', $user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getCustomerUser() {
|
||||||
|
return $this->get('customer_user');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clearCustomerUser() {
|
||||||
|
return $this->remove('customer_user');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function setAdminUser(UserInterface $user) {
|
||||||
|
$this->set('admin_user', $user);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getAdminUser() {
|
||||||
|
return $this->get('admin_user');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clearAdminUser() {
|
||||||
|
return $this->remove('admin_user');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,60 +0,0 @@
|
|||||||
<?php
|
|
||||||
/*************************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* Thelia */
|
|
||||||
/* */
|
|
||||||
/* Copyright (c) OpenStudio */
|
|
||||||
/* email : info@thelia.net */
|
|
||||||
/* web : http://www.thelia.net */
|
|
||||||
/* */
|
|
||||||
/* This program is free software; you can redistribute it and/or modify */
|
|
||||||
/* it under the terms of the GNU General Public License as published by */
|
|
||||||
/* the Free Software Foundation; either version 3 of the License */
|
|
||||||
/* */
|
|
||||||
/* This program is distributed in the hope that it will be useful, */
|
|
||||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
||||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
||||||
/* GNU General Public License for more details. */
|
|
||||||
/* */
|
|
||||||
/* You should have received a copy of the GNU General Public License */
|
|
||||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************************/
|
|
||||||
|
|
||||||
namespace Thelia\Core\Security\Authentication;
|
|
||||||
|
|
||||||
use Thelia\Core\Security\UserNotFoundException;
|
|
||||||
use Thelia\Core\Security\IncorrectPasswordException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Aunthentication providers are in charge or retrieving users, and check their
|
|
||||||
* credentials.
|
|
||||||
*
|
|
||||||
* @author Franck
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
interface AuthenticationProviderInterface {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the authentication token
|
|
||||||
*
|
|
||||||
* @param TokenInterface $token the authentication token
|
|
||||||
*/
|
|
||||||
public function setToken(TokenInterface $token);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set the authentication token
|
|
||||||
*
|
|
||||||
* @param unknown $key
|
|
||||||
*/
|
|
||||||
public function supportsToken(TokenInterface $token);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Authenticate the token
|
|
||||||
*
|
|
||||||
*@throws Exception if authentication was not successful
|
|
||||||
*/
|
|
||||||
public function authenticate();
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
/*************************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* Thelia */
|
|
||||||
/* */
|
|
||||||
/* Copyright (c) OpenStudio */
|
|
||||||
/* email : info@thelia.net */
|
|
||||||
/* web : http://www.thelia.net */
|
|
||||||
/* */
|
|
||||||
/* This program is free software; you can redistribute it and/or modify */
|
|
||||||
/* it under the terms of the GNU General Public License as published by */
|
|
||||||
/* the Free Software Foundation; either version 3 of the License */
|
|
||||||
/* */
|
|
||||||
/* This program is distributed in the hope that it will be useful, */
|
|
||||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
||||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
||||||
/* GNU General Public License for more details. */
|
|
||||||
/* */
|
|
||||||
/* You should have received a copy of the GNU General Public License */
|
|
||||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************************/
|
|
||||||
|
|
||||||
namespace Thelia\Core\Security\Authentication;
|
|
||||||
|
|
||||||
use Thelia\Core\Security\Authentication\AuthenticationProviderInterface;
|
|
||||||
use Thelia\Core\Security\Encoder\PasswordEncoderInterface;
|
|
||||||
use Thelia\Core\Security\User\UserProviderInterface;
|
|
||||||
use Thelia\Security\Token\TokenInterface;
|
|
||||||
use Thelia\Core\Security\Exception\IncorrectPasswordException;
|
|
||||||
use Thelia\Core\Security\Token\UsernamePasswordToken;
|
|
||||||
|
|
||||||
class UsernamePasswordAuthenticator implements AuthenticationProviderInterface {
|
|
||||||
|
|
||||||
protected $userProvider;
|
|
||||||
protected $encoder;
|
|
||||||
|
|
||||||
private $token;
|
|
||||||
|
|
||||||
public function __construct(UserProviderInterface $userProvider, PasswordEncoderInterface $encoder) {
|
|
||||||
$this->userProvider = $userProvider;
|
|
||||||
$this->encoder = $encoder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function supportsToken(TokenInterface $token) {
|
|
||||||
|
|
||||||
return $token instanceof UsernamePasswordToken;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function authenticate($token) {
|
|
||||||
|
|
||||||
if (!$this->supports($token)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retreive user
|
|
||||||
$user = $this->userProvider->getUser($this->token->getUsername());
|
|
||||||
|
|
||||||
// Check password
|
|
||||||
$authOk = $this->encoder->isEqual($password, $user->getPassword(), $user->getAlgo(), $user->getSalt()) === true;
|
|
||||||
|
|
||||||
$authenticatedToken = new UsernamePasswordToken($user, $token->getCredentials(), $authOk);
|
|
||||||
|
|
||||||
return $authenticatedToken;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
<?php
|
|
||||||
use Thelia\Core\Security\Token\UsernamePasswordToken;
|
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
|
||||||
use Thelia\Core\Security\Authentication\UsernamePasswordAuthenticator;
|
|
||||||
use Thelia\Core\Security\User\UserProvider\CustomerUserProvider;
|
|
||||||
use Thelia\Core\Security\Encoder\PasswordHashEncoder;
|
|
||||||
use Symfony\Component\DependencyInjection\ContainerInterface;
|
|
||||||
|
|
||||||
class AuthenticationProcessor {
|
|
||||||
|
|
||||||
private $container;
|
|
||||||
|
|
||||||
public function __construct(ContainerInterface $container) {
|
|
||||||
$this->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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
<?php
|
|
||||||
/*************************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* Thelia */
|
|
||||||
/* */
|
|
||||||
/* Copyright (c) OpenStudio */
|
|
||||||
/* email : info@thelia.net */
|
|
||||||
/* web : http://www.thelia.net */
|
|
||||||
/* */
|
|
||||||
/* This program is free software; you can redistribute it and/or modify */
|
|
||||||
/* it under the terms of the GNU General Public License as published by */
|
|
||||||
/* the Free Software Foundation; either version 3 of the License */
|
|
||||||
/* */
|
|
||||||
/* This program is distributed in the hope that it will be useful, */
|
|
||||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
||||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
||||||
/* GNU General Public License for more details. */
|
|
||||||
/* */
|
|
||||||
/* You should have received a copy of the GNU General Public License */
|
|
||||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************************/
|
|
||||||
|
|
||||||
namespace Thelia\Core\Security\Encoder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This interface defines a password encoder.
|
|
||||||
*
|
|
||||||
* @author Franck Allimant <franck@cqfdev.fr>
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
interface PasswordEncoderInterface {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a string.
|
|
||||||
*
|
|
||||||
* @param string $password the password to encode
|
|
||||||
* @param string $algorithm the hash() algorithm
|
|
||||||
* @return string $salt the salt
|
|
||||||
*/
|
|
||||||
public function encode($password, $algorithm, $salt);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check a string against an encoded password.
|
|
||||||
*
|
|
||||||
* @param string $string the string to compare against password
|
|
||||||
* @param string $password the encoded password
|
|
||||||
* @param string $algorithm the hash() algorithm
|
|
||||||
* @return string $salt the salt
|
|
||||||
*/
|
|
||||||
public function isEqual($string, $password, $algorithm, $salt);
|
|
||||||
}
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
<?php
|
|
||||||
/*************************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* Thelia */
|
|
||||||
/* */
|
|
||||||
/* Copyright (c) OpenStudio */
|
|
||||||
/* email : info@thelia.net */
|
|
||||||
/* web : http://www.thelia.net */
|
|
||||||
/* */
|
|
||||||
/* This program is free software; you can redistribute it and/or modify */
|
|
||||||
/* it under the terms of the GNU General Public License as published by */
|
|
||||||
/* the Free Software Foundation; either version 3 of the License */
|
|
||||||
/* */
|
|
||||||
/* This program is distributed in the hope that it will be useful, */
|
|
||||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
||||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
||||||
/* GNU General Public License for more details. */
|
|
||||||
/* */
|
|
||||||
/* You should have received a copy of the GNU General Public License */
|
|
||||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************************/
|
|
||||||
|
|
||||||
namespace Thelia\Core\Security\Encoder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This interface defines a hash based password encoder.
|
|
||||||
*
|
|
||||||
* @author Franck Allimant <franck@cqfdev.fr>
|
|
||||||
*/
|
|
||||||
|
|
||||||
class PasswordHashEncoder implements PasswordEncoderInterface {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function encode($password, $algorithm, $salt)
|
|
||||||
{
|
|
||||||
if (!in_array($algorithm, hash_algos(), true)) {
|
|
||||||
throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $algorithm));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Salt the string
|
|
||||||
$salted = $password.$salt;
|
|
||||||
|
|
||||||
// Create the hash
|
|
||||||
$digest = hash($algorithm, $salted, true);
|
|
||||||
|
|
||||||
// "stretch" hash
|
|
||||||
for ($i = 1; $i < 5000; $i++) {
|
|
||||||
$digest = hash($algorithm, $digest.$salted, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
return base64_encode($digest);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function isEqual($string, $password, $algorithm, $salt)
|
|
||||||
{
|
|
||||||
$encoded = $this->encode($password, $algorithm, $salt);
|
|
||||||
|
|
||||||
return $encoded == $string;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
<?php
|
|
||||||
/*************************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* Thelia */
|
|
||||||
/* */
|
|
||||||
/* Copyright (c) OpenStudio */
|
|
||||||
/* email : info@thelia.net */
|
|
||||||
/* web : http://www.thelia.net */
|
|
||||||
/* */
|
|
||||||
/* This program is free software; you can redistribute it and/or modify */
|
|
||||||
/* it under the terms of the GNU General Public License as published by */
|
|
||||||
/* the Free Software Foundation; either version 3 of the License */
|
|
||||||
/* */
|
|
||||||
/* This program is distributed in the hope that it will be useful, */
|
|
||||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
||||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
||||||
/* GNU General Public License for more details. */
|
|
||||||
/* */
|
|
||||||
/* You should have received a copy of the GNU General Public License */
|
|
||||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************************/
|
|
||||||
namespace Thelia\Core\Security\Encoder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* use password api include in php 5.5 and available throw the password_compat library.
|
|
||||||
*
|
|
||||||
* Class PasswordPhpCompatEncoder
|
|
||||||
* @package Thelia\Core\Security\Encoder
|
|
||||||
*/
|
|
||||||
class PasswordPhpCompatEncoder implements PasswordEncoderInterface {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Encode a string.
|
|
||||||
*
|
|
||||||
* @param string $password the password to encode
|
|
||||||
* @param string $algorithm the hash() algorithm
|
|
||||||
* @return string $salt the salt, the salt is not used here.
|
|
||||||
*/
|
|
||||||
public function encode($password, $algorithm, $salt = null)
|
|
||||||
{
|
|
||||||
return password_hash($password, $algorithm);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check a string against an encoded password.
|
|
||||||
*
|
|
||||||
* @param string $string the string to compare against password
|
|
||||||
* @param string $password the encoded password
|
|
||||||
* @param string $algorithm the hash() algorithm, not used here
|
|
||||||
* @return string $salt the salt, not used here
|
|
||||||
*/
|
|
||||||
public function isEqual($string, $password, $algorithm = null, $salt = null)
|
|
||||||
{
|
|
||||||
return password_verify($string, $password);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
<?php
|
|
||||||
/*************************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* Thelia */
|
|
||||||
/* */
|
|
||||||
/* Copyright (c) OpenStudio */
|
|
||||||
/* email : info@thelia.net */
|
|
||||||
/* web : http://www.thelia.net */
|
|
||||||
/* */
|
|
||||||
/* This program is free software; you can redistribute it and/or modify */
|
|
||||||
/* it under the terms of the GNU General Public License as published by */
|
|
||||||
/* the Free Software Foundation; either version 3 of the License */
|
|
||||||
/* */
|
|
||||||
/* This program is distributed in the hope that it will be useful, */
|
|
||||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
||||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
||||||
/* GNU General Public License for more details. */
|
|
||||||
/* */
|
|
||||||
/* You should have received a copy of the GNU General Public License */
|
|
||||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************************/
|
|
||||||
|
|
||||||
namespace Thelia\Core\Security\Exception;
|
|
||||||
|
|
||||||
class AuthenticationTokenNotFoundException extends \Exception
|
|
||||||
{
|
|
||||||
}
|
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
* file that was distributed with this source code.
|
* file that was distributed with this source code.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace use Thelia\Core\Security\Role;
|
namespace Thelia\Core\Security\Role;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Role is a simple implementation of a RoleInterface where the role is a
|
* Role is a simple implementation of a RoleInterface where the role is a
|
||||||
|
|||||||
@@ -25,62 +25,125 @@ namespace Thelia\Core\Security;
|
|||||||
|
|
||||||
use Thelia\Core\Security\Authentication\AuthenticationProviderInterface;
|
use Thelia\Core\Security\Authentication\AuthenticationProviderInterface;
|
||||||
use Thelia\Core\Security\Exception\AuthenticationTokenNotFoundException;
|
use Thelia\Core\Security\Exception\AuthenticationTokenNotFoundException;
|
||||||
|
use Thelia\Core\Security\Token\TokenInterface;
|
||||||
|
use Thelia\Core\Security\User\UserInterface;
|
||||||
|
use Thelia\Core\HttpFoundation\Request;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple security manager, in charge of authenticating users using various authentication systems.
|
* A simple security manager, in charge of checking user
|
||||||
*
|
*
|
||||||
* @author Franck Allimant <franck@cqfdev.fr>
|
* @author Franck Allimant <franck@cqfdev.fr>
|
||||||
*/
|
*/
|
||||||
class SecurityContext {
|
class SecurityContext {
|
||||||
/*
|
|
||||||
protected $authProvider;
|
|
||||||
|
|
||||||
public function __construct(AuthenticationProviderInterface $authProvider) {
|
const CONTEXT_FRONT_OFFICE = 'front';
|
||||||
$this->authProvider = $authProvider;
|
const CONTEXT_BACK_OFFICE = 'admin';
|
||||||
}
|
|
||||||
*/
|
private $request;
|
||||||
|
private $context;
|
||||||
|
|
||||||
|
public function __construct(Request $request) {
|
||||||
|
|
||||||
|
$this->request = $request;
|
||||||
|
|
||||||
|
$this->context = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setContext($context) {
|
||||||
|
if ($context !== self::CONTEXT_FRONT_OFFICE && $context !== self::CONTEXT_BACK_OFFICE) {
|
||||||
|
throw new \InvalidArgumentException(sprintf("Invalid or empty context identifier '%s'", $context));
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->context = $context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getContext($exception_if_context_undefined = false) {
|
||||||
|
if (null === $this->context && $exception_if_context_undefined === true)
|
||||||
|
throw new \LogicException("No context defined. Please use setContext() first.");
|
||||||
|
|
||||||
|
return $this->context;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getSession() {
|
||||||
|
$session = $this->request->getSession();
|
||||||
|
|
||||||
|
if ($session === null)
|
||||||
|
throw new \LogicException("No session found.");
|
||||||
|
|
||||||
|
return $session;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the current token is authenticated
|
* Gets the currently authenticated user in the current context, or null if none is defined
|
||||||
*
|
*
|
||||||
* @throws AuthenticationCredentialsNotFoundException when the security context has no authentication token.
|
* @return UserInterface|null A UserInterface instance or null if no user is available
|
||||||
|
*/
|
||||||
|
public function getUser() {
|
||||||
|
$context = $this->getContext(true);
|
||||||
|
|
||||||
|
if ($context === self::CONTEXT_FRONT_OFFICE)
|
||||||
|
$user = $this->getSession()->getCustomerUser();
|
||||||
|
else if ($context == self::CONTEXT_BACK_OFFICE)
|
||||||
|
$user = $this->getSession()->getAdminUser();
|
||||||
|
else
|
||||||
|
$user = null;
|
||||||
|
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
|
|
||||||
|
final public function isAuthenticated()
|
||||||
|
{
|
||||||
|
if (null !== $this->getUser()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the current user is allowed
|
||||||
*
|
*
|
||||||
* @return Boolean
|
* @return Boolean
|
||||||
* @throws AuthenticationTokenNotFoundException if no thoken was found in context
|
|
||||||
*/
|
*/
|
||||||
final public function isGranted($roles, $permissions)
|
final public function isGranted($roles, $permissions)
|
||||||
{
|
{
|
||||||
if (null === $this->token) {
|
if ($this->isAuthenticated() === true) {
|
||||||
throw new AuthenticationTokenNotFoundException('The security context contains no authentication token.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!$this->token->isAuthenticated()) {
|
echo "TODO: check roles and permissions !";
|
||||||
$this->token = $this->authProvider->authenticate($this->token);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->token->isAuthenticated()) {
|
// TODO : check roles and permissions
|
||||||
// Check user roles and permissions
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the currently authenticated token.
|
* Sets the authenticated user.
|
||||||
*
|
*
|
||||||
* @return TokenInterface|null A TokenInterface instance or null if no authentication information is available
|
* @param UserInterface $user A UserInterface, or null if no further user should be stored
|
||||||
*/
|
*/
|
||||||
public function getToken()
|
public function setUser(UserInterface $user)
|
||||||
{
|
{
|
||||||
return $this->token;
|
$context = $this->getContext(true);
|
||||||
|
|
||||||
|
$user->eraseCredentials();
|
||||||
|
|
||||||
|
if ($context === self::CONTEXT_FRONT_OFFICE)
|
||||||
|
$this->getSession()->setCustomerUser($user);
|
||||||
|
else if ($context == self::CONTEXT_BACK_OFFICE)
|
||||||
|
$this->getSession()->setAdminUser($user);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the token.
|
* Clear the user from the security context
|
||||||
*
|
*/
|
||||||
* @param TokenInterface $token A TokenInterface token, or null if no further authentication information should be stored
|
public function clear() {
|
||||||
*/
|
$context = $this->getContext(true);
|
||||||
public function setToken(TokenInterface $token = null)
|
|
||||||
{
|
if ($context === self::CONTEXT_FRONT_OFFICE)
|
||||||
$this->token = $token;
|
$this->getSession()->clearCustomerUser();
|
||||||
|
else if ($context == self::CONTEXT_BACK_OFFICE)
|
||||||
|
$this->getSession()->clearAdminUser();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,148 +0,0 @@
|
|||||||
<?php
|
|
||||||
namespace Thelia\Core\Security\Token;
|
|
||||||
|
|
||||||
use Thelia\Core\Security\User\UserInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base class for Token instances.
|
|
||||||
*
|
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
|
||||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
|
||||||
*/
|
|
||||||
abstract class AbstractToken implements TokenInterface
|
|
||||||
{
|
|
||||||
private $user;
|
|
||||||
private $authenticated;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param RoleInterface[] $roles An array of roles
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException
|
|
||||||
*/
|
|
||||||
public function __construct()
|
|
||||||
{
|
|
||||||
$this->authenticated = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function getUsername()
|
|
||||||
{
|
|
||||||
if ($this->user instanceof UserInterface) {
|
|
||||||
return $this->user->getUsername();
|
|
||||||
}
|
|
||||||
|
|
||||||
return (string) $this->user;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getUser()
|
|
||||||
{
|
|
||||||
return $this->user;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the user in the token.
|
|
||||||
*
|
|
||||||
* The user can be a UserInterface instance, or an object implementing
|
|
||||||
* a __toString method or the username as a regular string.
|
|
||||||
*
|
|
||||||
* @param mixed $user The user
|
|
||||||
* @throws \InvalidArgumentException
|
|
||||||
*/
|
|
||||||
public function setUser($user)
|
|
||||||
{
|
|
||||||
if (!($user instanceof UserInterface || is_string($user))) {
|
|
||||||
throw new \InvalidArgumentException('$user must be an instanceof UserInterface, or a primitive string.');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (null === $this->user) {
|
|
||||||
$changed = false;
|
|
||||||
} elseif ($this->user instanceof UserInterface) {
|
|
||||||
if (!$user instanceof UserInterface) {
|
|
||||||
$changed = true;
|
|
||||||
} else {
|
|
||||||
$changed = $this->hasUserChanged($user);
|
|
||||||
}
|
|
||||||
} elseif ($user instanceof UserInterface) {
|
|
||||||
$changed = true;
|
|
||||||
} else {
|
|
||||||
$changed = (string) $this->user !== (string) $user;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($changed) {
|
|
||||||
$this->setAuthenticated(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->user = $user;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function isAuthenticated()
|
|
||||||
{
|
|
||||||
return $this->authenticated;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function setAuthenticated($authenticated)
|
|
||||||
{
|
|
||||||
$this->authenticated = (Boolean) $authenticated;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function eraseCredentials()
|
|
||||||
{
|
|
||||||
if ($this->getUser() instanceof UserInterface) {
|
|
||||||
$this->getUser()->eraseCredentials();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function serialize()
|
|
||||||
{
|
|
||||||
return serialize(array($this->user, $this->authenticated));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function unserialize($serialized)
|
|
||||||
{
|
|
||||||
list($this->user, $this->authenticated) = unserialize($serialized);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function hasUserChanged(UserInterface $user)
|
|
||||||
{
|
|
||||||
if (!($this->user instanceof UserInterface)) {
|
|
||||||
throw new \BadMethodCallException('Method "hasUserChanged" should be called when current user class is instance of "UserInterface".');
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->user instanceof EquatableInterface) {
|
|
||||||
return ! (Boolean) $this->user->isEqualTo($user);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->user->getPassword() !== $user->getPassword()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->user->getSalt() !== $user->getSalt()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($this->user->getUsername() !== $user->getUsername()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
<?php
|
|
||||||
/*************************************************************************************/
|
|
||||||
/* */
|
|
||||||
/* Thelia */
|
|
||||||
/* */
|
|
||||||
/* Copyright (c) OpenStudio */
|
|
||||||
/* email : info@thelia.net */
|
|
||||||
/* web : http://www.thelia.net */
|
|
||||||
/* */
|
|
||||||
/* This program is free software; you can redistribute it and/or modify */
|
|
||||||
/* it under the terms of the GNU General Public License as published by */
|
|
||||||
/* the Free Software Foundation; either version 3 of the License */
|
|
||||||
/* */
|
|
||||||
/* This program is distributed in the hope that it will be useful, */
|
|
||||||
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
|
|
||||||
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
|
|
||||||
/* GNU General Public License for more details. */
|
|
||||||
/* */
|
|
||||||
/* You should have received a copy of the GNU General Public License */
|
|
||||||
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
|
||||||
/* */
|
|
||||||
/*************************************************************************************/
|
|
||||||
|
|
||||||
namespace Thelia\Core\Security\Token;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TokenInterface is the interface for the user authentication information.
|
|
||||||
*
|
|
||||||
* Parts borrowed from Symfony Security Framework (Fabien Potencier <fabien@symfony.com> / Johannes M. Schmitt <schmittjoh@gmail.com>)
|
|
||||||
*/
|
|
||||||
|
|
||||||
interface TokenInterface extends \Serializable
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Returns the user credentials.
|
|
||||||
*
|
|
||||||
* @return mixed The user credentials
|
|
||||||
*/
|
|
||||||
public function getCredentials();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns a user representation.
|
|
||||||
*
|
|
||||||
* @return mixed either returns an object which implements __toString(), or
|
|
||||||
* a primitive string is returned.
|
|
||||||
*/
|
|
||||||
public function getUser();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets a user instance
|
|
||||||
*
|
|
||||||
* @param mixed $user
|
|
||||||
*/
|
|
||||||
public function setUser($user);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the username.
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
public function getUsername();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the user is authenticated or not.
|
|
||||||
*
|
|
||||||
* @return Boolean true if the token has been authenticated, false otherwise
|
|
||||||
*/
|
|
||||||
public function isAuthenticated();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the authenticated flag.
|
|
||||||
*
|
|
||||||
* @param Boolean $isAuthenticated The authenticated flag
|
|
||||||
*/
|
|
||||||
public function setAuthenticated($isAuthenticated);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes sensitive information from the token.
|
|
||||||
*/
|
|
||||||
public function eraseCredentials();
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace Thelia\Core\Security\Token;
|
|
||||||
|
|
||||||
use Thelia\Core\Security\User\UserInterface;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UsernamePasswordToken implements a username and password token.
|
|
||||||
*
|
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
|
||||||
*/
|
|
||||||
class UsernamePasswordToken extends AbstractToken
|
|
||||||
{
|
|
||||||
private $credentials;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param string $user The username (like a nickname, email address, etc.), or a UserInterface instance or an object implementing a __toString method.
|
|
||||||
* @param string $password The password of the user
|
|
||||||
*
|
|
||||||
* @throws \InvalidArgumentException
|
|
||||||
*/
|
|
||||||
public function __construct($username, $password, array $roles = array())
|
|
||||||
{
|
|
||||||
$this->setUser($username);
|
|
||||||
$this->credentials = $password;
|
|
||||||
|
|
||||||
parent::setAuthenticated(count($roles) > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function setAuthenticated($isAuthenticated)
|
|
||||||
{
|
|
||||||
if ($isAuthenticated) {
|
|
||||||
throw new \LogicException('Cannot set this token to trusted after instantiation.');
|
|
||||||
}
|
|
||||||
|
|
||||||
parent::setAuthenticated(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getCredentials()
|
|
||||||
{
|
|
||||||
return $this->credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function eraseCredentials()
|
|
||||||
{
|
|
||||||
parent::eraseCredentials();
|
|
||||||
|
|
||||||
$this->credentials = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function serialize()
|
|
||||||
{
|
|
||||||
return serialize(array($this->credentials, $this->providerKey, parent::serialize()));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritdoc}
|
|
||||||
*/
|
|
||||||
public function unserialize($serialized)
|
|
||||||
{
|
|
||||||
list($this->credentials, $this->providerKey, $parentStr) = unserialize($serialized);
|
|
||||||
parent::unserialize($parentStr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -21,14 +21,9 @@ interface UserInterface {
|
|||||||
public function getPassword();
|
public function getPassword();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return the salt used to calculate the user password
|
* Check a string against a the user password
|
||||||
*/
|
*/
|
||||||
public function getSalt();
|
public function checkPassword($password);
|
||||||
|
|
||||||
/**
|
|
||||||
* return the algorithm used to calculate the user password
|
|
||||||
*/
|
|
||||||
public function getAlgo();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the roles granted to the user.
|
* Returns the roles granted to the user.
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Thelia\Core\Security\User\UserProvider;
|
namespace Thelia\Core\Security\UserProvider;
|
||||||
|
|
||||||
|
use Thelia\Model\Admin;
|
||||||
|
use Thelia\Model\AdminQuery;
|
||||||
|
|
||||||
class AdminUserProvider implements UserProviderInterface {
|
class AdminUserProvider implements UserProviderInterface {
|
||||||
|
|
||||||
public function getUser($key) {
|
public function getUser($key) {
|
||||||
|
|
||||||
$admin = new Admin();
|
|
||||||
|
|
||||||
$admin = AdminQuery::create()
|
$admin = AdminQuery::create()
|
||||||
->filterByLogin($key)
|
->filterByLogin($key)
|
||||||
->findOne();
|
->findOne();
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<?php
|
<?php
|
||||||
namespace Thelia\Core\Security\User\UserProvider;
|
namespace Thelia\Core\Security\UserProvider;
|
||||||
|
|
||||||
|
|
||||||
|
use Thelia\Action\Customer;
|
||||||
|
use Thelia\Model\CustomerQuery;
|
||||||
class CustomerUserProvider implements UserProviderInterface {
|
class CustomerUserProvider implements UserProviderInterface {
|
||||||
|
|
||||||
public function getUser($key) {
|
public function getUser($key) {
|
||||||
|
|
||||||
$customer = new Customer();
|
|
||||||
|
|
||||||
$customer = CustomerQuery::create()
|
$customer = CustomerQuery::create()
|
||||||
->filterByEmail($key)
|
->filterByEmail($key)
|
||||||
->findOne();
|
->findOne();
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace Thelia\Core\Security\User\UserProvider;
|
namespace Thelia\Core\Security\UserProvider;
|
||||||
|
|
||||||
interface UserProviderInterface {
|
interface UserProviderInterface {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
namespace Thelia\Core\Template\Smarty\Assets;
|
namespace Thelia\Core\Template\Smarty\Assets;
|
||||||
|
|
||||||
use Thelia\Core\Template\Assets\AsseticHelper;
|
use Thelia\Core\Template\Assets\AsseticHelper;
|
||||||
|
use Thelia\Model\ConfigQuery;
|
||||||
|
|
||||||
class SmartyAssetsManager
|
class SmartyAssetsManager
|
||||||
{
|
{
|
||||||
@@ -71,7 +72,7 @@ class SmartyAssetsManager
|
|||||||
$url = $this->assetic_manager->asseticize(
|
$url = $this->assetic_manager->asseticize(
|
||||||
$asset_dir.'/'.$asset_file,
|
$asset_dir.'/'.$asset_file,
|
||||||
$this->web_root."/".$this->path_relative_to_web_root,
|
$this->web_root."/".$this->path_relative_to_web_root,
|
||||||
$this->path_relative_to_web_root,
|
ConfigQuery::read('base_url', '/') . $this->path_relative_to_web_root,
|
||||||
$assetType,
|
$assetType,
|
||||||
$filters,
|
$filters,
|
||||||
$debug
|
$debug
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ use Thelia\Core\Template\Smarty\SmartyPluginDescriptor;
|
|||||||
use Thelia\Core\Template\Smarty\SmartyPluginInterface;
|
use Thelia\Core\Template\Smarty\SmartyPluginInterface;
|
||||||
use Thelia\Core\Template\Smarty\Assets\SmartyAssetsManager;
|
use Thelia\Core\Template\Smarty\Assets\SmartyAssetsManager;
|
||||||
use Thelia\Core\Security\SecurityContext;
|
use Thelia\Core\Security\SecurityContext;
|
||||||
|
use Thelia\Core\Security\Exception\AuthenticationException;
|
||||||
|
|
||||||
class Security implements SmartyPluginInterface
|
class Security implements SmartyPluginInterface
|
||||||
{
|
{
|
||||||
@@ -39,7 +40,6 @@ class Security implements SmartyPluginInterface
|
|||||||
|
|
||||||
private function _explode($commaSeparatedValues)
|
private function _explode($commaSeparatedValues)
|
||||||
{
|
{
|
||||||
|
|
||||||
$array = explode(',', $commaSeparatedValues);
|
$array = explode(',', $commaSeparatedValues);
|
||||||
|
|
||||||
if (array_walk($array, function(&$item) {
|
if (array_walk($array, function(&$item) {
|
||||||
@@ -60,10 +60,23 @@ class Security implements SmartyPluginInterface
|
|||||||
*/
|
*/
|
||||||
public function checkAuthFunction($params, &$smarty)
|
public function checkAuthFunction($params, &$smarty)
|
||||||
{
|
{
|
||||||
$roles = $this->_explode($params['role']);
|
// Context: 'front' or 'admin'
|
||||||
|
$context = strtolower(trim($params['context']));
|
||||||
|
|
||||||
|
$this->securityContext->setContext($context);
|
||||||
|
|
||||||
|
$roles = $this->_explode($params['roles']);
|
||||||
$permissions = $this->_explode($params['permissions']);
|
$permissions = $this->_explode($params['permissions']);
|
||||||
|
|
||||||
$this->securityContext->isGranted($roles, $permissions);
|
if (! $this->securityContext->isGranted($roles, $permissions)) {
|
||||||
|
throw new AuthenticationException(
|
||||||
|
sprintf("User not granted for roles '%s', permissions '%s' in context '%s'.",
|
||||||
|
implode(',', $roles), implode(',', $permissions), $context
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -25,9 +25,16 @@ namespace Thelia\Core\Template\Smarty\Plugins;
|
|||||||
|
|
||||||
use Thelia\Core\Template\Smarty\SmartyPluginDescriptor;
|
use Thelia\Core\Template\Smarty\SmartyPluginDescriptor;
|
||||||
use Thelia\Core\Template\Smarty\SmartyPluginInterface;
|
use Thelia\Core\Template\Smarty\SmartyPluginInterface;
|
||||||
|
use Symfony\Component\Translation\TranslatorInterface;
|
||||||
|
|
||||||
class Translation implements SmartyPluginInterface
|
class Translation implements SmartyPluginInterface
|
||||||
{
|
{
|
||||||
|
protected $translator;
|
||||||
|
|
||||||
|
public function __construct(TranslatorInterface $translator) {
|
||||||
|
$this->translator = $translator;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process translate function
|
* Process translate function
|
||||||
*
|
*
|
||||||
@@ -35,16 +42,9 @@ class Translation implements SmartyPluginInterface
|
|||||||
* @param unknown $smarty
|
* @param unknown $smarty
|
||||||
* @return string
|
* @return string
|
||||||
*/
|
*/
|
||||||
public function theliaTranslate($params, &$smarty)
|
public function translate($params, &$smarty)
|
||||||
{
|
{
|
||||||
if (isset($params['l'])) {
|
return $this->translator->trans($params['l'], isset($params['p']) ? $params['p'] : array());
|
||||||
$string = str_replace('\'', '\\\'', $params['l']);
|
|
||||||
} else {
|
|
||||||
$string = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO
|
|
||||||
return "$string";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,7 +55,7 @@ class Translation implements SmartyPluginInterface
|
|||||||
public function getPluginDescriptors()
|
public function getPluginDescriptors()
|
||||||
{
|
{
|
||||||
return array(
|
return array(
|
||||||
new SmartyPluginDescriptor('function', 'intl', $this, 'theliaTranslate'),
|
new SmartyPluginDescriptor('function', 'intl', $this, 'translate'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,12 +44,12 @@ class AdminLogin extends BaseForm {
|
|||||||
new NotBlank()
|
new NotBlank()
|
||||||
)
|
)
|
||||||
))
|
))
|
||||||
->add("remember_me", "checkbox");
|
->add("remember_me", "checkbox")
|
||||||
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getName()
|
public function getName()
|
||||||
{
|
{
|
||||||
return "admin_login";
|
return "admin_login";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
namespace Thelia\Model;
|
namespace Thelia\Model;
|
||||||
|
|
||||||
use Thelia\Core\Security\User\UserInterface;
|
use Thelia\Core\Security\User\UserInterface;
|
||||||
|
use Thelia\Core\Security\Role\Role;
|
||||||
|
|
||||||
use Thelia\Model\Base\Admin as BaseAdmin;
|
use Thelia\Model\Base\Admin as BaseAdmin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,9 +20,34 @@ use Thelia\Model\Base\Admin as BaseAdmin;
|
|||||||
*/
|
*/
|
||||||
class Admin extends BaseAdmin implements UserInterface
|
class Admin extends BaseAdmin implements UserInterface
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public function setPassword($password)
|
||||||
|
{
|
||||||
|
\Thelia\Log\Tlog::getInstance()->debug($password);
|
||||||
|
|
||||||
|
if ($this->isNew() && ($password === null || trim($password) == "")) {
|
||||||
|
throw new InvalidArgumentException("customer password is mandatory on creation");
|
||||||
|
}
|
||||||
|
|
||||||
|
if($password !== null && trim($password) != "") {
|
||||||
|
$this->setAlgo("PASSWORD_BCRYPT");
|
||||||
|
return parent::setPassword(password_hash($password, PASSWORD_BCRYPT));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
public function checkPassword($password)
|
||||||
|
{
|
||||||
|
return password_verify($password, $this->password);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
public function getUsername() {
|
public function getUsername() {
|
||||||
return $this->getLogin();
|
return $this->getLogin();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,37 @@
|
|||||||
namespace Thelia\Model;
|
namespace Thelia\Model;
|
||||||
|
|
||||||
use Thelia\Model\Base\AdminLog as BaseAdminLog;
|
use Thelia\Model\Base\AdminLog as BaseAdminLog;
|
||||||
|
use Thelia\Core\HttpFoundation\Request;
|
||||||
|
use Thelia\Log\Tlog;
|
||||||
|
use Thelia\Model\Base\Admin as BaseAdminUser;
|
||||||
|
|
||||||
class AdminLog extends BaseAdminLog {
|
class AdminLog extends BaseAdminLog {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A sdimple helper to insert an entry in the admin log
|
||||||
|
*
|
||||||
|
* @param unknown $actionLabel
|
||||||
|
* @param Request $request
|
||||||
|
* @param Admin $adminUser
|
||||||
|
*/
|
||||||
|
public static function append($actionLabel, Request $request, BaseAdminUser $adminUser = null) {
|
||||||
|
|
||||||
|
$log = new AdminLog();
|
||||||
|
|
||||||
|
$log
|
||||||
|
->setAdminLogin($adminUser !== null ? $adminUser->getLogin() : '<no login>')
|
||||||
|
->setAdminFirstname($adminUser !== null ? $adminUser->getFirstname() : '<no first name>')
|
||||||
|
->setAdminLastname($adminUser !== null ? $adminUser->getLastname() : '<no last name>')
|
||||||
|
->setAction($actionLabel)
|
||||||
|
->setRequest($request->__toString())
|
||||||
|
;
|
||||||
|
|
||||||
|
try {
|
||||||
|
$log->save();
|
||||||
|
}
|
||||||
|
catch (\Exception $ex) {
|
||||||
|
Tlog::getInstance()->err("Failed to insert new entry in AdminLog: {ex}", array('ex' => $ex));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -113,12 +113,19 @@ class Customer extends BaseCustomer implements UserInterface
|
|||||||
$this->dispatcher = $dispatcher;
|
$this->dispatcher = $dispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
*/
|
||||||
|
public function getUsername() {
|
||||||
|
return $this->getEmail();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
|
public function checkPassword($password)
|
||||||
public function getUsername() {
|
{
|
||||||
return $this->getEmail();
|
return password_verify($password, $this->password);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,75 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
use Thelia\Core\Security\Encoder\PasswordHashEncoder;
|
|
||||||
|
|
||||||
class PasswordHashEncoderTest extends \PHPUnit_Framework_TestCase
|
|
||||||
{
|
|
||||||
public function testEncode()
|
|
||||||
{
|
|
||||||
$encoder = new PasswordHashEncoder();
|
|
||||||
|
|
||||||
$pass = $encoder->encode('password', 'sha512', 'a simple salt');
|
|
||||||
|
|
||||||
// echo "PASS=\{$pass\}";
|
|
||||||
|
|
||||||
$this->assertEquals("L3f/gGy4nBVhi8WSsC1a7E9JM8U+rtk6ZT+NiqX8M1UDJv6mahQEZ1z2cN/y9pixH+hgWbkBitONMiXWscomoQ==", $pass, "Expected password not found.");
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testIsEqual()
|
|
||||||
{
|
|
||||||
$encoder = new PasswordHashEncoder();
|
|
||||||
|
|
||||||
$exp = "L3f/gGy4nBVhi8WSsC1a7E9JM8U+rtk6ZT+NiqX8M1UDJv6mahQEZ1z2cN/y9pixH+hgWbkBitONMiXWscomoQ==";
|
|
||||||
|
|
||||||
$this->assertTrue($encoder->isEqual($exp, 'password', 'sha512', 'a simple salt'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testWrongPass()
|
|
||||||
{
|
|
||||||
$encoder = new PasswordHashEncoder();
|
|
||||||
|
|
||||||
$exp = "L3f/gGy4nBVhi8WSsC1a7E9JM8U+rtk6ZT+NiqX8M1UDJv6mahQEZ1z2cN/y9pixH+hgWbkBitONMiXWscomoQ==";
|
|
||||||
|
|
||||||
$this->assertFalse($encoder->isEqual($exp, 'grongron', 'sha512', 'a simple salt'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testWrongSalt()
|
|
||||||
{
|
|
||||||
$encoder = new PasswordHashEncoder();
|
|
||||||
|
|
||||||
$exp = "L3f/gGy4nBVhi8WSsC1a7E9JM8U+rtk6ZT+NiqX8M1UDJv6mahQEZ1z2cN/y9pixH+hgWbkBitONMiXWscomoQ==";
|
|
||||||
|
|
||||||
$this->assertFalse($encoder->isEqual($exp, 'password', 'sha512', 'another salt'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testWrongAlgo()
|
|
||||||
{
|
|
||||||
$encoder = new PasswordHashEncoder();
|
|
||||||
|
|
||||||
$exp = "L3f/gGy4nBVhi8WSsC1a7E9JM8U+rtk6ZT+NiqX8M1UDJv6mahQEZ1z2cN/y9pixH+hgWbkBitONMiXWscomoQ==";
|
|
||||||
|
|
||||||
$this->assertFalse($encoder->isEqual($exp, 'password', 'md5', 'another salt'));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException LogicException
|
|
||||||
*/
|
|
||||||
public function testUnsupportedAlgo()
|
|
||||||
{
|
|
||||||
$encoder = new PasswordHashEncoder();
|
|
||||||
|
|
||||||
$exp = "L3f/gGy4nBVhi8WSsC1a7E9JM8U+rtk6ZT+NiqX8M1UDJv6mahQEZ1z2cN/y9pixH+hgWbkBitONMiXWscomoQ==";
|
|
||||||
|
|
||||||
$encoder->isEqual($exp, 'password', 'sbonk', 'another salt');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @expectedException LogicException
|
|
||||||
*/
|
|
||||||
public function testEncodeWrongAlgorithm()
|
|
||||||
{
|
|
||||||
$encoder = new PasswordHashEncoder();
|
|
||||||
|
|
||||||
$encoder->encode('password', 'pouët', 'a simple salt');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
<?php
|
|
||||||
/**
|
|
||||||
* Created by JetBrains PhpStorm.
|
|
||||||
* User: manu
|
|
||||||
* Date: 09/07/13
|
|
||||||
* Time: 10:02
|
|
||||||
* To change this template use File | Settings | File Templates.
|
|
||||||
*/
|
|
||||||
|
|
||||||
namespace Thelia\Tests\Security\Encoder;
|
|
||||||
|
|
||||||
|
|
||||||
use Thelia\Core\Security\Encoder\PasswordPhpCompatEncoder;
|
|
||||||
|
|
||||||
class PasswordPhpCompatEncoderTest extends \PHPUnit_Framework_TestCase {
|
|
||||||
|
|
||||||
protected $encoder;
|
|
||||||
|
|
||||||
public function setUp()
|
|
||||||
{
|
|
||||||
$this->encoder = new PasswordPhpCompatEncoder();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function testEncode()
|
|
||||||
{
|
|
||||||
$hash = $this->encoder->encode("foo", PASSWORD_BCRYPT);
|
|
||||||
|
|
||||||
$this->assertEquals($hash, crypt("foo", $hash));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{check_auth roles="ADMIN"}
|
{check_auth context="admin" roles="ADMIN"}
|
||||||
{$page_title={intl l='Home'}}
|
{$page_title={intl l='Home'}}
|
||||||
{include file='includes/header.inc.html'}
|
{include file='includes/header.inc.html'}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<hr />
|
<hr />
|
||||||
<footer class="modal-footer">
|
<footer class="modal-footer">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<p>{intl l='© Thelia 2012'}
|
<p>{intl l='© Thelia 2013'}
|
||||||
- <a href="http://www.openstudio.fr/" target="_blank">{intl l='Édité par OpenStudio'}</a>
|
- <a href="http://www.openstudio.fr/" target="_blank">{intl l='Édité par OpenStudio'}</a>
|
||||||
- <a href="http://forum.thelia.net/" target="_blank">{intl l='Forum Thelia'}</a>
|
- <a href="http://forum.thelia.net/" target="_blank">{intl l='Forum Thelia'}</a>
|
||||||
- <a href="http://contrib.thelia.net/" target="_blank">{intl l='Contributions Thelia'}</a>
|
- <a href="http://contrib.thelia.net/" target="_blank">{intl l='Contributions Thelia'}</a>
|
||||||
|
|||||||
@@ -13,23 +13,27 @@
|
|||||||
<div class="hero-unit">
|
<div class="hero-unit">
|
||||||
<h1>{intl l='Thelia Back Office'}</h1>
|
<h1>{intl l='Thelia Back Office'}</h1>
|
||||||
|
|
||||||
<form action="admin/login" method="post" class="well form-inline" {form_enctype form=$form}>
|
<form action="checklogin" method="post" class="well form-inline" {form_enctype form=$form}>
|
||||||
|
|
||||||
|
{if isset($message)}<div class="alert alert-error">{$message}</div>{/if}
|
||||||
|
|
||||||
{form_field_hidden form=$form}
|
{form_field_hidden form=$form}
|
||||||
|
|
||||||
{form_field form=$form.username}
|
{form_field form=$form.username}
|
||||||
{form_error form=$form.username}
|
{form_error form=$form.username}{$message}{/form_error}
|
||||||
{$message}
|
|
||||||
{/form_error}
|
|
||||||
<input type="text" class="input" placeholder="{intl l='E-mail address'}" name="{$name}" />
|
<input type="text" class="input" placeholder="{intl l='E-mail address'}" name="{$name}" />
|
||||||
{/form_field}
|
{/form_field}
|
||||||
|
|
||||||
{form_field form=$form.password}
|
{form_field form=$form.password}
|
||||||
|
{form_error form=$form.password}{$message}{/form_error}
|
||||||
<input type="password" class="input" placeholder="{intl l='Password'}" name="{$name}" />
|
<input type="password" class="input" placeholder="{intl l='Password'}" name="{$name}" />
|
||||||
{/form_field}
|
{/form_field}
|
||||||
|
|
||||||
{form_field form=$form.remember_me}
|
{form_field form=$form.remember_me}
|
||||||
<label class="checkbox"> <input type="checkbox" name="remember" value="yes"> {intl l='Remember me'}</label>
|
<label class="checkbox"> <input type="checkbox" name="remember" value="yes" /> {intl l='Remember me'}</label>
|
||||||
{/form_field}
|
{/form_field}
|
||||||
|
|
||||||
<div class="pull-right"><button type="submit" class="btn btn-primary">{intl l='Login'} <i class="icon-play icon-white"></i></button></div>
|
<span class="pull-right"><button type="submit" class="btn btn-primary">{intl l='Login'} <i class="icon-play icon-white"></i></button></span>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>{intl l='Hi, I\'m a Thelia TPex template'}</title>
|
<title>{intl l="Hi, I'm a Thelia TPex template"}</title>
|
||||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
|
||||||
{stylesheets file='../assets/css/*' filters='less,cssembed'}
|
{stylesheets file='../assets/css/*' filters='less,cssembed'}
|
||||||
|
|||||||
Reference in New Issue
Block a user