Symfony2 ACL access to multiple objects for multiple users
Asked Answered
R

1

6

I'm busy with a Symfony2 application that needs some ACL permissions.

I'm a newbie with Symfony2, so not sure if i'm looking at this the right way.

I have multiple clients, each with multiple accounts.

I have a super admin (ROLE_SUPER_ADMIN) that have access to all clients and all accounts. Then I have an admin role (ROLE_ADMIN), which will only be allowed access to a specific client and all accounts for that clients. Then there is agents (ROLE_AGENT), which should only have permission to certain accounts for clients.

I saw on the symfony docs that to give a user access to a specific object, I can use the following code:

// creating the ACL
$aclProvider = $this->get('security.acl.provider');
$objectIdentity = ObjectIdentity::fromDomainObject($account);
$acl = $aclProvider->createAcl($objectIdentity);

// retrieving the security identity of the currently logged-in user
$securityContext = $this->get('security.context');
$user = $securityContext->getToken()->getUser();
$securityIdentity = UserSecurityIdentity::fromAccount($user);

// grant owner access    
$acl->insertObjectAce($securityIdentity, MaskBuilder::MASK_OWNER);
$aclProvider->updateAcl($acl);

So when creating a new account, I can give the current logged-in user access to the newly created account. But how do I grant access to all the other users of the client access to the account?

I don't want to loop through all users and run the above code for every user.

So for example when viewing all clients, I need to know which clients the user has access to, or when viewing the accounts, I need to know which accounts the user has access to.

Also when adding a new user to a client, the user automatically need to have access to all the accounts for that client.

As a side note, I only need to know if the user has access to the account/client. If a user has access, then they are automatically allowed to view/edit/delete etc.

Roath answered 28/8, 2012 at 20:44 Comment(1)
If you need to assign permissions to every user in specific role you you should use role-based ACL instead... which is much alike account-based. I should be able to write some example code (in next few hours). However if roles is not something you're after, you ** will ** need to iterate through each user you want to assign permission to....Ambitious
P
0

For this case I used a custom security service that verifies ManyToMany relations between entities. It`s not the ideal decision but keep in mind.

First we need to make listener that will be triggered at every controller action.

class SecurityListener
{
    protected $appSecurity;

    function __construct(AppSecurity $appSecurity)
    {
        $this->appSecurity = $appSecurity;
    }

    public function onKernelController(FilterControllerEvent $event)
    {
        $c = $event->getController();

        /*
         * $controller passed can be either a class or a Closure. This is not usual in Symfony2 but it may happen.
         * If it is a class, it comes in array format
         */
        if (!is_array($c)) {
            return;
        }

        $hasAccess = $this->appSecurity->hasAccessToContoller($c[0], $c[1], $event->getRequest());

        if(!$hasAccess) {
            throw new AccessDeniedHttpException('Access denied.');
        }

    }
}

In service we have access to request, controller instance and called action. So we can make a decision have user access or not.

class AppSecurity
{
    protected $em;
    protected $security;
    /** @var $user User */
    protected $user;

    public function __construct(EntityManager $em, SecurityContext $security)
    {
        $this->em = $em;
        $this->security = $security;

        if($security->getToken() !== null && !$security->getToken() instanceof AnonymousToken) {
            $this->user = $security->getToken()->getUser();
        }
    }

    /**
     * @param $controller
     * @param string $action
     */
    public function hasAccessToContoller($controller, $action, Request $request)
    {
        $attrs = $request->attributes->all();
        $client = $attrs['client'];

        /* db query to check link between logged user and request client */
    }
}

If you are using very nasty annotations like ParamConverter you can easily extract ready to use entites from request.

Pepi answered 9/8, 2013 at 10:31 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.