2014-12-16 3 views
2

Я пытаюсь реализовать пользовательский избиратель.Symfony2 custom Voter: не может быть доступ к getDoctrine изнутри Избирателя

От контроллера я называю это следующим образом:

$prj = $this->getDoctrine()->getRepository('AppBundle:Project')->findOneById($id); 
if (false === $this->get('security.authorization_checker')->isGranted('responsible', $prj)) { 
    throw new AccessDeniedException('Unauthorised access!'); 
} 

Первая строка правильно извлекает объект проекта (я проверил с отвала).

Проблема возникает внутри избирателя

<?php 
namespace AppBundle\Security\Authorization\Voter; 

use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface; 
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface; 
use Symfony\Component\Security\Core\User\UserInterface; 


class ProjectVoter implements VoterInterface 
{ 
    const RESPONSIBLE = 'responsible'; 
    const ACCOUNTABLE = 'accountable'; 
    const SUPPORT = 'support'; 
    const CONSULTED = 'consulted'; 
    const INFORMED = 'informed'; 

    public function supportsAttribute($attribute) 
    { 
     return in_array($attribute, array(
      self::RESPONSIBLE, 
      self::ACCOUNTABLE, 
      self::SUPPORT, 
      self::CONSULTED, 
      self::INFORMED, 
     )); 
    } 

    public function supportsClass($class) 
    { 
     $supportedClass = 'AppBundle\Entity\Project'; 

     return $supportedClass === $class || is_subclass_of($class, $supportedClass); 
    } 

    /** 
    * @var \AppBundle\Entity\Project $project 
    */ 
    public function vote(TokenInterface $token, $project, array $attributes) 
    { 
     // check if class of this object is supported by this voter 
     if (!$this->supportsClass(get_class($project))) { 
      return VoterInterface::ACCESS_ABSTAIN; 
     } 

     // check if the voter is used correct, only allow one attribute 
     // this isn't a requirement, it's just one easy way for you to 
     // design your voter 
     if (1 !== count($attributes)) { 
      throw new \InvalidArgumentException(
       'Only one attribute is allowed' 
      ); //in origin it was 'for VIEW or EDIT, which were the supported attributes 
     } 

     // set the attribute to check against 
     $attribute = $attributes[0]; 

     // check if the given attribute is covered by this voter 
     if (!$this->supportsAttribute($attribute)) { 
      return VoterInterface::ACCESS_ABSTAIN; 
     } 

     // get current logged in user 
     $user = $token->getUser(); 

     // make sure there is a user object (i.e. that the user is logged in) 
     if (!$user instanceof UserInterface) { 
      return VoterInterface::ACCESS_DENIED; 
     } 

     $em = $this->getDoctrine()->getManager(); 
     $projects = $em->getRepository('AppBundle:Project')->findPrjByUserAndRole($user, $attribute); 

     foreach ($projects as $key => $prj) { 
      if ($prj['id'] === $project['id']) 
       { 
       $granted = true; 
       $index = $key; // save the index of the last time a specifif project changed status 
       } 
      } 
     if($projects[$index]['is_active']===true) //if the last status is active 
      return VoterInterface::ACCESS_GRANTED; 
     else 
      return VoterInterface::ACCESS_DENIED; 
    } 
} 

Я получаю следующую ошибку

Пытались вызвать метод "getDoctrine" на классе "AppBundle \ Security \ Authorization \ Избиратель \ ProjectVoter".

Я понимаю, что контроллер расширяет контроллер, поэтому я могу использовать «getDoctrine». Как я могу получить доступ к моей БД изнутри избирателя?

ответ

6

Я решил. Это довольно любопытно: я провожу несколько часов или дней на проблему, то задайте вопрос здесь, и я решаю это сам в течение часа:/

мне нужно добавить следующее в моем классе избирателей:

public function __construct(EntityManager $em) 
{ 
    $this->em = $em; 
} 

мне нужно добавить следующее в верхней:

use Doctrine\ORM\EntityManager; 

Я также необходимо добавить аргументы в service.yml

security.access.project_voter: 
    class:  AppBundle\Security\Authorization\Voter\ProjectVoter 
    arguments: [ @doctrine.orm.entity_manager ] 
    public:  false 
    tags: 
     - { name: security.voter } 
+0

Да, в любое время, когда вы хотите использовать другую услугу в своем собственном сервисе, вам нужно сначала ввести ее, как вы это делали выше. –

+3

На symfony 3 вам нужно добавить двойные кавычки для аргументов аргументов: ["@ doctrine.orm.entity_manager"] 'else это не удается –

 Смежные вопросы

  • Нет связанных вопросов^_^