Showing posts with label Sonata. Show all posts
Showing posts with label Sonata. Show all posts

Tuesday, July 12, 2016

Symfony/Sonata ACL - search for the object owner

Lately I am wrestling with the ACL in a project using Symfony with Sonata Admin Bundle and Sonata User Bundle. When editing objects from the admin panel offered by Sonata Admin Bundle things go smoothly, but the issues is how to set ACL permissions for objects I create in my own controllers.

Situation:

 An Admin1 user --> creates a Regular1 user --> which creates Objects and save them to database.

Problem:

Make Regular1 user and Admin1 user  owners of the newly created Object.

Note: Admin user is not ROLE_SUPER_ADMIN, just a custom role I have in my app

Solution:

First step, in the createAction controller method, after persisting my object, set the current user (Regular user) as owner of the object.


<?php 
    public function createAction(Request $request)
    {
        .....
        $em->persist($myObject);
        $em->flush();
            
        // retrieve services and get current user
        $adminSecurityHandler = $this->container->get('sonata.admin.security.handler');
        $modelAdmin = $this->container->get('admin.sites');
        $user = $this->getUser();

        $securityIdentity = UserSecurityIdentity::fromAccount($user);

        $objectIdentity = ObjectIdentity::fromDomainObject($myObject);
        $acl = $adminSecurityHandler->getObjectAcl($objectIdentity);
        
        if (is_null($acl)) {
            $acl = $adminSecurityHandler->createAcl($objectIdentity);
        }
        $adminSecurityHandler->addObjectClassAces($acl, $adminSecurityHandler->buildSecurityInformation($modelAdmin));
        $adminSecurityHandler->addObjectOwner($acl,$securityIdentity);  // set current user as owner in ACL

        $adminSecurityHandler->updateAcl($acl);

Second part is to search for the Admin user, owner of the regular user (which is currently logged).
Looking into the list of ACE associated to the object identity, I am searching for the one with  Mask equal to 128 (owner mask).


<?php

        //search for the owner (admin user) of the current user and give him privileges on the "myObject" object
        $userObjectIdentity = ObjectIdentity::fromDomainObject($user);
        $userObjectACL = $adminSecurityHandler->getObjectAcl($userObjectIdentity);

        $aces= $userObjectACL->getObjectAces();    
       
        /*
         *  $aces is an array containing ACEs, objects from this class: 
         *  http://api.symfony.com/2.7/Symfony/Component/Security/Acl/Domain/Entry.html
         */
        foreach($aces as $ace){
            if(128 === $ace->getMask()){
                $adminSecurityIdentity = $ace->getSecurityIdentity();
                $adminSecurityHandler->addObjectOwner($acl,$adminSecurityIdentity);  
                $adminSecurityHandler->updateAcl($acl);
            }
        }