0

I am trying to restrict user access from accessing the CRUD access in the controller.

I have a bi-directional OneToOne relationship with User and Category. It's setup to only allow 1 user to be able to access 1 blog.

I am testing this by logging in as another user that is not related to this category. And upon clicking on new, the form loads by-passing any security I have setup.

Speculating that the problem is with the $title parameter being passed in, (trying to pass this in as the route variable) as I don't think I'm setting this up correctly.

Can someone guide me on what I'm doing wrong?

Controller code

/**
 * Post controller.
 *
 * @Route("/category")
 */

/**
 * Creates a new Post entity.
 *
 * @Route("/", name="category_create")
 * @Method("POST")
 * @Template("AcmeDemoBundle:Page:new.html.twig")
 */
public function createAction(Request $request, $title)
{
    // User security
    $em = $this->getDoctrine()->getManager();

    $categoryRepository = $em->getRepository('AcmeDemoBundle:Category');

    $category = $categoryRepository->findOneBy(array(
        'title' => '$title',
    ));

    $owner = $category->getUser();

    $currentUser = $this->get('security.context')->getToken()->getUser();

    if ($owner != $currentUser) {
        throw new AccessDeniedException('You do not have access for this');
    }

    // Form creation
    $post = new Post();

    $form = $this->createCreateForm($post);
    $form->handleRequest($request);

    if ($form->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $em->persist($post);
        $em->flush();

        return $this->redirect($this->generateUrl('category_show', array('id' => $post->getId())));
    }

    return array(
        'post' => $post,
        'form' => $form->createView(),
    );
}

Category entity

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="title", type="string", length=255)
 */
private $title;

/**
 * @var string
 *
 * @Gedmo\Slug(fields={"title"}, unique=false)
 * @ORM\Column(length=255)
 */
private $catslug;

/**
 * @ORM\OneToMany(targetEntity="Post", mappedBy="category")
 */
protected $posts;

/**
 * @ORM\OneToOne(targetEntity="Acme\DemoBundle\Entity\User", inversedBy="cat")
 * @ORM\JoinColumn(name="cat_id", referencedColumnName="id")
 */
protected $user;

User entity

/**
 * @var integer
 *
 * @ORM\Column(name="id", type="integer")
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="AUTO")
 */
private $id;

/**
 * @var string
 *
 * @ORM\Column(name="username", type="string", length=255)
 * @Assert\NotBlank(message="Field cannot be blank")
 */
private $username;

/**
 * @var string
 *
 * @ORM\Column(name="password", type="string", length=255)
 */
private $password;

/**
 * @ORM\Column(type="string", length=255)
 * @Assert\NotBlank()
 */
private $email;

/**
 * @ORM\Column(type="json_array")
 */
private $roles = array();

/**
 * @var bool
 *
 * @ORM\Column(type="boolean")
 */
private $isActive = true;

/**
 * @Assert\NotBlank
 * @Assert\Regex(
 *     pattern="/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?!.*\s).*$/",
 *     message="Use 1 upper case letter, 1 lower case letter, and 1 number")
 */
private $plainPassword;

/**
 * @ORM\OneToOne(targetEntity="Acme\DemoBundle\Entity\Category", mappedBy="user")
 */
private $cat;
chance
  • 315
  • 5
  • 15

1 Answers1

0

You can try to create own Security Voter to check if user has a permission to this action. Sample code:

class CategoryVoter implements VoterInterface
{
    const CREATE = 'create';

    /**
     * @param string $attribute
     * @return bool
     */
    public function supportsAttribute($attribute)
    {
        return in_array($attribute, [
            self::CREATE
        ]);
    }

    /**
     * @param string $class
     * @return bool
     */
    public function supportsClass($class)
    {
        $supportedClass = 'Acme\DemoBundle\Entity\Category';

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

    /**
     * @param TokenInterface $token
     * @param object $blog
     * @param array $attributes
     * @return int
     */
    public function vote(TokenInterface $token, Category $category, array $attributes)
    {
        ....

        $attribute = $attributes[0];
        $user = $token->getUser();

        switch($attribute) {
            case 'create':
                if ($user->getId() === $category->getUser()->getId()) {
                    return VoterInterface::ACCESS_GRANTED;
                }
                break;

            ....
        }

        ...
    }
}

create action:

public function createAction(Request $request, $title)
{
    $em = $this->getDoctrine()->getManager();

    $categoryRepository = $em->getRepository('AcmeDemoBundle:Category');

    $category = $categoryRepository->findOneBy([
        'title' => '$title',
    ]);

    ...

    if (false === $this->get('security.context')->isGranted('create', $category)) {
        throw new AccessDeniedException('Unauthorised access!');
    }

    ...
}
xurshid29
  • 4,172
  • 1
  • 20
  • 25