Symfony 2 - ACL check permission based on 'separate' roles

Viewed 5239

Let's say we have 3 main roles that are directly bound to the database table user: ROLE_USER, ROLE_MODERATOR and ROLE_ADMIN.

BUT, we also got some other roles, which are used for the Crews component (see UML below). I use the following roles for actions peformed in a Crew: ROLE_CREW_BOSS, ROLE_CREW_LEFTHAND, ROLE_CREW_RIGHTHAND, ROLE_CREW_MEMBER.



      +----------------+                                     +------------------+
      | users          |                                     | crews            |
      |----------------|                                     |------------------|
      | id             |                                     | id               |
      | username       <---+                                 | name             |
      | password       |   |                             +---> cash             |
      | roles          |   |    +-------------------+    |   | ...              |
      | ...            |   |    | crew_members      |    |   |                  |
      |                |   |    |-------------------|    |   |                  |
      +----------------+   |    | crew_id +--------------+   |                  |
                           +----+ user_id           |        +--------^---------+
                                | roles             |                 |
                                | ...               |    +------------+
                                |                   |    |
                                |                   |    |   +------------------+
                                |                   |    |   | forum_topics     |
                                |                   |    |   |------------------|
                                |                   |    |   | id               |
                                +-------------------+    +---+ crew_id          |
                                                             | title            |
                                                             | description      |
                                                             | ...              |
                                                             |                  |
                                                             |                  |
                                                             |                  |
                                                             +------------------+

That is the base structure, I hope that part is clear. Now comes the problem...

The problem

Every user with the role ROLE_MODERATOR can create ForumTopic objects, but not the one where crew_id is set, because that one is private for a specific crew. Also, only crew members (which are also users) that have the role ROLE_CREW_BOSS, ROLE_CREW_LEFTHAND or ROLE_CREW_RIGHTHAND can edit the forum topics of their crew. How do I check those kind of complexity? With a Voter maybe?

UPDATE 1

I have solved the problem for 50%, but it's not solid. I've created a voter specific for the object Entity\\ForumTopic.

public function vote(TokenInterface $token, $object, array $attributes)
{
    if ($object instanceof ObjectIdentityInterface) {
        if ($object->getType() == 'Entity\\ForumTopic') {

            /**
             * @var Member $member
             */
            $member = $token->getUser();

            $userTable = new UserTable();
            $user = $userTable->getByMember($member);

            $userInCrewTable = new UserInCrewTable();
            $crewMember = $userInCrewTable->getByUser($user);

            if ($crewMember && in_array($crewMember->getRole(), array('boss', 'lefthand', 'righthand'))) {
                return self::ACCESS_GRANTED;
            }
        }
    }

    return self::ACCESS_ABSTAIN;
}

The only problem here is that I don't use the respective roles, so I can't use the role hierarchy functionality for example. Anyone got a better solution or a improvement on my current solution?

Thanks!

Steffen

3 Answers
Related