Removed InternalEvent, simplified SecurityContext

This commit is contained in:
franck
2013-08-28 17:52:32 +02:00
parent 253a0b76d8
commit 0361cd1ff2
26 changed files with 630 additions and 610 deletions

View File

@@ -40,52 +40,6 @@ class BaseAction
$this->container = $container;
}
/**
* Validate a BaseForm
*
* @param BaseForm $aBaseForm the form
* @param string $expectedMethod the expected method, POST or GET, or null for any of them
* @throws FormValidationException is the form contains error, or the method is not the right one
* @return \Symfony\Component\Form\Form Form the symfony form object
*/
protected function validateForm(BaseForm $aBaseForm, $expectedMethod = null)
{
$form = $aBaseForm->getForm();
if ($expectedMethod == null || $aBaseForm->getRequest()->isMethod($expectedMethod)) {
$form->bind($aBaseForm->getRequest());
if ($form->isValid()) {
return $form;
} else {
throw new FormValidationException("Missing or invalid data");
}
} else {
throw new FormValidationException(sprintf("Wrong form method, %s expected.", $expectedMethod));
}
}
/**
* Propagate a form error in the action event
*
* @param BaseForm $aBaseForm the form
* @param string $error_message an error message that may be displayed to the customer
* @param ActionEvent $event the action event
*/
protected function propagateFormError(BaseForm $aBaseForm, $error_message, ActionEvent $event)
{
// The form has an error
$aBaseForm->setError(true);
$aBaseForm->setErrorMessage($error_message);
// Store the form in the parser context
$event->setErrorForm($aBaseForm);
// Stop event propagation
$event->stopPropagation();
}
/**
* Return the event dispatcher,
*
@@ -96,4 +50,33 @@ class BaseAction
return $this->container->get('event_dispatcher');
}
}
/**
* Check current user authorisations.
*
* @param mixed $roles a single role or an array of roles.
* @param mixed $permissions a single permission or an array of permissions.
*
* @throws AuthenticationException if permissions are not granted to the current user.
*/
protected function checkAuth($roles, $permissions) {
if (! $this->getSecurityContext()->isGranted(
is_array($roles) ? $roles : array($roles),
is_array($permissions) ? $permissions : array($permissions)) ) {
Tlog::getInstance()->addAlert("Authorization roles:", $roles, " permissions:", $permissions, " refused.");
throw new AuthorizationException("Sorry, you're not allowed to perform this action");
}
}
/**
* Return the security context
*
* @return Thelia\Core\Security\SecurityContext
*/
protected function getSecurityContext()
{
return $this->container->get('thelia.securityContext');
}
}

View File

@@ -24,134 +24,46 @@
namespace Thelia\Action;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Thelia\Core\Event\ActionEvent;
use Thelia\Core\Event\TheliaEvents;
use Thelia\Model\Category as CategoryModel;
use Thelia\Form\CategoryCreationForm;
use Thelia\Core\Event\CategoryEvent;
use Thelia\Tools\Redirect;
use Thelia\Model\CategoryQuery;
use Thelia\Model\AdminLog;
use Thelia\Form\CategoryDeletionForm;
use Thelia\Action\Exception\FormValidationException;
use Propel\Runtime\ActiveQuery\Criteria;
use Propel\Runtime\Propel;
use Thelia\Model\Map\CategoryTableMap;
use Propel\Runtime\Exception\PropelException;
use Thelia\Core\Event\CategoryCreateEvent;
use Thelia\Core\Event\CategoryDeleteEvent;
use Thelia\Core\Event\CategoryToggleVisibilityEvent;
use Thelia\Core\Event\CategoryChangePositionEvent;
class Category extends BaseAction implements EventSubscriberInterface
{
public function create(ActionEvent $event)
public function create(CategoryCreateEvent $event)
{
$this->checkAuth("ADMIN", "admin.category.create");
$request = $event->getRequest();
$category = new CategoryModel();
try {
$categoryCreationForm = new CategoryCreationForm($request);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CREATECATEGORY, $event);
$form = $this->validateForm($categoryCreationForm, "POST");
$category->create(
$event->getTitle(),
$event->getParent(),
$event->getLocale()
);
$data = $form->getData();
$event->setCreatedCategory($category);
$category = new CategoryModel();
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CREATECATEGORY, $event);
$category->create(
$data["title"],
$data["parent"],
$data["locale"]
);
AdminLog::append(sprintf("Category %s (ID %s) created", $category->getTitle(), $category->getId()), $request, $request->getSession()->getAdminUser());
$categoryEvent = new CategoryEvent($category);
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECATEGORY, $categoryEvent);
// Substitute _ID_ in the URL with the ID of the created category
$successUrl = str_replace('_ID_', $category->getId(), $categoryCreationForm->getSuccessUrl());
// Redirect to the success URL
$this->redirect($successUrl);
} catch (PropelException $e) {
Tlog::getInstance()->error(sprintf('error during creating category with message "%s"', $e->getMessage()));
$message = "Failed to create this category, please try again.";
}
// The form has errors, propagate it.
$this->propagateFormError($categoryCreationForm, $message, $event);
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CREATECATEGORY, $event);
}
public function modify(ActionEvent $event)
public function modify(CategoryChangeEvent $event)
{
$this->checkAuth("ADMIN", "admin.category.change");
$this->checkAuth("ADMIN", "admin.category.delete");
$request = $event->getRequest();
$customerModification = new CustomerModification($request);
$form = $customerModification->getForm();
if ($request->isMethod("post")) {
$form->bind($request);
if ($form->isValid()) {
$data = $form->getData();
$customer = CustomerQuery::create()->findPk(1);
try {
$customerEvent = new CustomerEvent($customer);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECUSTOMER, $customerEvent);
$data = $form->getData();
$customer->createOrUpdate(
$data["title"],
$data["firstname"],
$data["lastname"],
$data["address1"],
$data["address2"],
$data["address3"],
$data["phone"],
$data["cellphone"],
$data["zipcode"],
$data["country"]
);
$customerEvent->customer = $customer;
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECUSTOMER, $customerEvent);
// Update the logged-in user, and redirect to the success URL (exits)
// We don-t send the login event, as the customer si already logged.
$this->processSuccessfullLogin($event, $customer, $customerModification);
} catch (PropelException $e) {
Tlog::getInstance()->error(sprintf('error during modifying customer on action/modifyCustomer with message "%s"', $e->getMessage()));
$message = "Failed to change your account, please try again.";
}
} else {
$message = "Missing or invalid data";
}
} else {
$message = "Wrong form method !";
}
// The form has an error
$customerModification->setError(true);
$customerModification->setErrorMessage($message);
// Dispatch the errored form
$event->setErrorForm($customerModification);
// TODO !!
}
/**
@@ -159,50 +71,22 @@ class Category extends BaseAction implements EventSubscriberInterface
*
* @param ActionEvent $event
*/
public function delete(ActionEvent $event)
public function delete(CategoryDeleteEvent $event)
{
$this->checkAuth("ADMIN", "admin.category.delete");
$request = $event->getRequest();
$category = CategoryQuery::create()->findPk($event->getId());
try {
$categoryDeletionForm = new CategoryDeletionForm($request);
if ($category !== null) {
$form = $this->validateForm($categoryDeletionForm, "POST");
$event->setDeletedCategory($category);
$data = $form->getData();
$category = CategoryQuery::create()->findPk($data['id']);
$categoryEvent = new CategoryEvent($category);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_DELETECATEGORY, $categoryEvent);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_DELETECATEGORY, $event);
$category->delete();
AdminLog::append(sprintf("Category %s (ID %s) deleted", $category->getTitle(), $category->getId()), $request, $request->getSession()->getAdminUser());
$categoryEvent->category = $category;
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_DELETECATEGORY, $categoryEvent);
// Substitute _ID_ in the URL with the ID of the created category
$successUrl = str_replace('_ID_', $category->getParent(), $categoryDeletionForm->getSuccessUrl());
// Redirect to the success URL
Redirect::exec($successUrl);
} catch (PropelException $e) {
\Thelia\Log\Tlog::getInstance()->error(sprintf('error during deleting category ID=%s on action/modifyCustomer with message "%s"', $data['id'], $e->getMessage()));
$message = "Failed to change your account, please try again.";
} catch (FormValidationException $e) {
$message = $e->getMessage();
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_DELETECATEGORY, $event);
}
$this->propagateFormError($categoryDeletionForm, $message, $event);
}
/**
@@ -210,63 +94,55 @@ class Category extends BaseAction implements EventSubscriberInterface
*
* @param ActionEvent $event
*/
public function toggleVisibility(ActionEvent $event)
public function toggleVisibility(CategoryToggleVisibilityEvent $event)
{
$this->checkAuth("ADMIN", "admin.category.edit");
$request = $event->getRequest();
$category = CategoryQuery::create()->findPk($request->get('category_id', 0));
$category = CategoryQuery::create()->findPk($event->getId());
if ($category !== null) {
$event->setCategory($category);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECATEGORY, $event);
$category->setVisible($category->getVisible() ? false : true);
$category->save();
$categoryEvent = new CategoryEvent($category);
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECATEGORY, $categoryEvent);
$event->setCategory($category);
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECATEGORY, $event);
}
}
/**
* Move category up
* Changes category position, selecting absolute ou relative change.
*
* @param ActionEvent $event
* @param CategoryChangePositionEvent $event
*/
public function changePositionUp(ActionEvent $event)
public function changePosition(CategoryChangePositionEvent $event)
{
return $this->exchangePosition($event, 'up');
}
$this->checkAuth("ADMIN", "admin.category.edit");
/**
* Move category down
*
* @param ActionEvent $event
*/
public function changePositionDown(ActionEvent $event)
{
return $this->exchangePosition($event, 'down');
if ($event->getMode() == CategoryChangePositionEvent::POSITION_ABSOLUTE)
return $this->changeAbsolutePosition($event);
else
return $this->exchangePosition($event);
}
/**
* Move up or down a category
*
* @param ActionEvent $event
* @param string $direction up to move up, down to move down
* @param CategoryChangePositionEvent $event
*/
protected function exchangePosition(ActionEvent $event, $direction)
protected function exchangePosition(CategoryChangePositionEvent $event)
{
$this->checkAuth("ADMIN", "admin.category.edit");
$request = $event->getRequest();
$category = CategoryQuery::create()->findPk($request->get('category_id', 0));
$category = CategoryQuery::create()->findPk($event->getId());
if ($category !== null) {
$event->setCategory($category);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECATEGORY, $event);
// The current position of the category
$my_position = $category->getPosition();
@@ -275,10 +151,10 @@ class Category extends BaseAction implements EventSubscriberInterface
->filterByParent($category->getParent());
// Up or down ?
if ($direction == 'up') {
if ($event->getMode() == CategoryChangePositionEvent::POSITION_UP) {
// Find the category immediately before me
$search->filterByPosition(array('max' => $my_position-1))->orderByPosition(Criteria::DESC);
} elseif ($direction == 'down') {
} elseif ($event->getMode() == CategoryChangePositionEvent::POSITION_DOWN) {
// Find the category immediately after me
$search->filterByPosition(array('min' => $my_position+1))->orderByPosition(Criteria::ASC);
} else
@@ -304,26 +180,30 @@ class Category extends BaseAction implements EventSubscriberInterface
$cnx->rollback();
}
}
$event->setCategory($category);
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECATEGORY, $event);
}
}
/**
* Changes category position
*
* @param ActionEvent $event
* @param CategoryChangePositionEvent $event
*/
public function changePosition(ActionEvent $event)
protected function changeAbsolutePosition(CategoryChangePositionEvent $event)
{
$this->checkAuth("ADMIN", "admin.category.edit");
$request = $event->getRequest();
$category = CategoryQuery::create()->findPk($request->get('category_id', 0));
$category = CategoryQuery::create()->findPk($event->getId());
if ($category !== null) {
$event->setCategory($category);
$event->getDispatcher()->dispatch(TheliaEvents::BEFORE_CHANGECATEGORY, $event);
// The required position
$new_position = $request->get('position', null);
$new_position = $event->getPosition();
// The current position
$current_position = $category->getPosition();
@@ -363,6 +243,9 @@ class Category extends BaseAction implements EventSubscriberInterface
$cnx->rollback();
}
}
$event->setCategory($category);
$event->getDispatcher()->dispatch(TheliaEvents::AFTER_CHANGECATEGORY, $event);
}
}
@@ -389,12 +272,14 @@ class Category extends BaseAction implements EventSubscriberInterface
public static function getSubscribedEvents()
{
return array(
"action.createCategory" => array("create", 128),
"action.modifyCategory" => array("modify", 128),
"action.deleteCategory" => array("delete", 128),
TheliaEvents::CATEGORY_CREATE => array("create", 128),
TheliaEvents::CATEGORY_MODIFY => array("modify", 128),
TheliaEvents::CATEGORY_DELETE => array("delete", 128),
"action.toggleCategoryVisibility" => array("toggleVisibility", 128),
"action.changeCategoryPositionUp" => array("changePositionUp", 128),
TheliaEvents::CATEGORY_TOGGLE_VISIBILITY => array("toggleVisibility", 128),
TheliaEvents::CATEGORY_CHANGE_POSITION => array("changePosition", 128),
"action.changeCategoryPositionU" => array("changePositionUp", 128),
"action.changeCategoryPositionDown" => array("changePositionDown", 128),
"action.changeCategoryPosition" => array("changePosition", 128),
);

View File

@@ -96,7 +96,7 @@ class Customer extends BaseAction implements EventSubscriberInterface
{
$event->getDispatcher()->dispatch(TheliaEvents::CUSTOMER_LOGOUT, $event);
$this->getFrontSecurityContext()->clear();
$this->getSecurityContext()->clearCustomerUser();
}
public function changePassword(ActionEvent $event)
@@ -127,8 +127,8 @@ class Customer extends BaseAction implements EventSubscriberInterface
public static function getSubscribedEvents()
{
return array(
"action.createCustomer" => array("create", 128),
"action.modifyCustomer" => array("modify", 128),
TheliaEvents::CUSTOMER_CREATEACCOUNT => array("create", 128),
TheliaEvents::CUSTOMER_UPDATEACCOUNT => array("modify", 128),
);
}
}