public function canUser($module, $function, ValueObject $object, array $targets = [])
{
$permissionSets = $this->hasAccess($module, $function);
if ($permissionSets === false || $permissionSets === true) {
return $permissionSets;
}
if (empty($targets)) {
$targets = null;
}
$currentUserRef = $this->getCurrentUserReference();
foreach ($permissionSets as $permissionSet) {
/**
* First deal with Role limitation if any.
*
* Here we accept ACCESS_GRANTED and ACCESS_ABSTAIN, the latter in cases where $object and $targets
* are not supported by limitation.
*
* @var \eZ\Publish\API\Repository\Values\User\Limitation[]
*/
if ($permissionSet['limitation'] instanceof Limitation) {
$type = $this->limitationService->getLimitationType($permissionSet['limitation']->getIdentifier());
$accessVote = $type->evaluate($permissionSet['limitation'], $currentUserRef, $object, $targets);
if ($accessVote === LimitationType::ACCESS_DENIED) {
continue;
}
}
/**
* Loop over all policies.
*
* These are already filtered by hasAccess and given hasAccess did not return boolean
* there must be some, so only return true if one of them says yes.
*
* @var \eZ\Publish\API\Repository\Values\User\Policy
*/
foreach ($permissionSet['policies'] as $policy) {
$limitations = $policy->getLimitations();
/*
* Return true if policy gives full access (aka no limitations)
*/
if ($limitations === '*') {
return true;
}
/*
* Loop over limitations, all must return ACCESS_GRANTED for policy to pass.
* If limitations was empty array this means same as '*'
*/
$limitationsPass = true;
foreach ($limitations as $limitation) {
$type = $this->limitationService->getLimitationType($limitation->getIdentifier());
$accessVote = $type->evaluate($limitation, $currentUserRef, $object, $targets);
/*
* For policy limitation atm only support ACCESS_GRANTED
*
* Reasoning: Right now, use of a policy limitation not valid for a policy is per definition a
* BadState. To reach this you would have to configure the "policyMap" wrongly, like using
* Node (Location) limitation on state/assign. So in this case Role Limitations will return
* ACCESS_ABSTAIN (== no access here), and other limitations will throw InvalidArgument above,
* both cases forcing dev to investigate to find miss configuration. This might be relaxed in
* the future if valid use cases for ACCESS_ABSTAIN on policy limitations becomes known.
*/
if ($accessVote !== LimitationType::ACCESS_GRANTED) {
$limitationsPass = false;
break;
// Break to next policy, all limitations must pass
}
}
if ($limitationsPass) {
return true;
}
}
}
return false;
// None of the limitation sets wanted to let you in, sorry!
}