Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Symfony voter: how do I check a user's role?

Tags:

php

symfony

I have Posts that are owned by a specific user. I've created a voter to check if the user owns the Post, but I also want admins (ie, ROLE_ADMIN and above) to be able to access all Posts.

I've followed the instructions (and nearly copied the code) on the How to Use Voters to Check User Permissions cookbook entry. Now I'm wondering how I do the check. Ideas:

  1. Pass another service into the Voter...not sure which one.
  2. Do something with the vote method.
  3. Don't do the check in the voter, but do it inside the controller (ie, don't call the voter check if they're an admin).
like image 513
Darryl Hein Avatar asked Dec 15 '25 08:12

Darryl Hein


1 Answers

This is what I came up with. Basically overrode the parent vote() method, adding the check for roles within it. The role check concerns me a bit since it isn't using any of the built in method, but I'm not sure they're accessible and that it won't create a loop (since role checking uses a voter as well). I've tagged the parts that are custom.

Let me know if anything is a big no no.

<?php
// src/AppBundle/Security/Authorization/Voter/PostVoter.php

namespace AppBundle\Security\Authorization\Voter;

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

class PostVoter extends AbstractVoter
{
    const VIEW = 'view';
    const EDIT = 'edit';

    /**
     * {@inheritDoc}
     */
    public function vote(TokenInterface $token, $object, array $attributes)
    {
        if (!$object || !$this->supportsClass(get_class($object))) {
            return self::ACCESS_ABSTAIN;
        }

        // ----------------------------------
        // -- start – custom
        $user = $token->getUser();
        if ($user instanceof UserInterface) {
            if (in_array('ROLE_SUPER_ADMIN', $user->getRoles())) {
                return self::ACCESS_GRANTED;
            }
        }
        // -- end – custom
        // ----------------------------------

        // abstain vote by default in case none of the attributes are supported
        $vote = self::ACCESS_ABSTAIN;

        foreach ($attributes as $attribute) {
            if (!$this->supportsAttribute($attribute)) {
                continue;
            }

            // as soon as at least one attribute is supported, default is to deny access
            $vote = self::ACCESS_DENIED;

            if ($this->isGranted($attribute, $object, $token->getUser())) {
                // grant access as soon as at least one voter returns a positive response
                return self::ACCESS_GRANTED;
            }
        }

        return $vote;
    }

    // ----------------------------------
    // -- start – custom
    protected function isGranted($attribute, $post, $user = null)
    {
        switch($attribute) {
            case self::VIEW:
                if ($post->getIsActive()) {
                    return true;
                }
                break;

            // must be owned by the current user or the user must be a super admin
            case self::EDIT:
                // make sure there is a user object (i.e. that the user is logged in)
                if (!$user instanceof UserInterface) {
                    return false;
                }

                if ($user->getId() === $post->getOwner()->getId()) {
                    return true;
                }
                break;
        }

        return false;
    }
    // -- end – custom
    // ----------------------------------

    protected function getSupportedAttributes()
    {
        return array(self::VIEW, self::EDIT);
    }

    protected function getSupportedClasses()
    {
        return array('AppBundle\Entity\Post');
    }

}
like image 178
Darryl Hein Avatar answered Dec 16 '25 22:12

Darryl Hein



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!