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