0

On an show user action, i want to check if the logged user has the right to see this user. So i created a UserVoter. But when I try to pass the user defined in the url to the Voter using annotation, I get the logged User using both $subject and $token->getUser()

If I change my var name in the action, it works fine ($user -> $foo).

Do you know how can I do for not changing my var name ?

Controller :

/**
 * Finds and displays a user entity.
 *
 * @Method("GET")
 * @Route("/{id}/", name="authenticated_user_show", requirements={"id": "\d+"})
 * @ParamConverter("user", class="AppBundle:User")
 * @Security("is_granted('SHOW', user)")
 */
public function showAction(User $user)
{

And Voter :

protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
{
    $user = $token->getUser();

    if (!$user instanceof User) {
        // the user must be logged in; if not, deny access
        return false;
    }

    if ($user->hasRole(User::ROLE_SUPER_ADMIN)) {
        // if super admin, can do everything
        return true;
    }

    // you know $subject is an User object, thanks to supports
    /** @var User $userSubject */
    $userSubject = $subject;

    switch ($attribute) {
        case self::SHOW:
            return $this->canShow($userSubject, $user);
        case self::EDIT:
            return $this->canEdit($userSubject, $user);
    }

    throw new \LogicException('This code should not be reached!');
}


private function canShow(User $userSubject, User $user) : bool
{
    if ($user->getClient() === $userSubject->getClient()) {
        // if they are in the same client
        return true;
    }

    return false;
}

private function canEdit(User $userSubject, User $user, TokenInterface $token) : bool
{
    if (
        $this->decisionManager->decide($token, [User::ROLE_ADMIN]) &&
        $user->getClient() === $userSubject->getClient()
        ) {
        // if the user and the admin belong to the same client
        return true;
    } elseif (
        $this->decisionManager->decide($token, [User::ROLE_MANAGER]) &&
        $this->userManager->hasEstablishmentInCommon($user, $userSubject)
        ) {
        // if the user and the manager are linked to the same establishment
        return true;
    }

    return false;
}
  • Your code looks alright so far. Can you double check that you aren't confusing users (order of parameters on $this->canShow and $this->canEdit) ? Can you share the code $this->canShow $this->canEdit? I will probably rename $user for $loggedUser to clarify a bit – albert Jun 20 '17 at 10:39
  • Thanks for the answer, I've edit the question to show you $this->canEdit(). But the probleme come from somewhere else, because when I do a `dump($user)` and `dump($userSubject)` in the voteOnAttribute function, both are the current logged user. – Theolephant Jul 05 '17 at 09:07

1 Answers1

0

Assuming that you are not trying to see the logged user I will consider that you may have a conflict with the variables in the security annotation context:

https://symfony.com/doc/current/bundles/SensioFrameworkExtraBundle/annotations/security.html The Security annotation has access to the following variables:

  • token: The current security token
  • user: The current user object
  • request: The request instance
  • roles: The user roles; and all request attributes.

To fix, change the name of the user so you can avoid the conflict.

/**
 * Finds and displays a user entity.
 *
 * @Method("GET")
 * @Route("/{id}/", name="authenticated_user_show", requirements={"id": 
   "\d+"})
 * @ParamConverter("showUser", class="AppBundle:User")
 * @Security("is_granted('SHOW', showUser)")
 */
 public function showAction(User $showUser)
albert
  • 4,290
  • 1
  • 21
  • 42