public function putInCache(AclInterface $acl) { if (null === $acl->getId()) { throw new \InvalidArgumentException('The given ACL does not have an ID.'); } $this->content[$acl->getId()] = $acl; }
public function configureACL(OutputInterface $output, AclInterface $acl, MaskBuilder $builder, array $aclInformations = array()) { foreach ($aclInformations as $name => $masks) { foreach ($masks as $mask) { $builder->add($mask); } $acl->insertClassAce(new RoleSecurityIdentity($name), $builder->get()); $output->writeln(sprintf(' - add role: %s, ACL: %s', $name, json_encode($masks))); $builder->reset(); } }
/** * {@inheritdoc} */ public function putInCache(AclInterface $acl) { if (null === $acl->getId()) { throw new \InvalidArgumentException('Transient ACLs cannot be cached.'); } $parentAcl = $acl->getParentAcl(); if (null !== $parentAcl) { $this->putInCache($parentAcl); } $key = $this->createKeyFromIdentity($acl->getObjectIdentity()); $this->cache->save($key, serialize($acl)); $this->cache->save($acl->getId(), $key); }
/** * {@inheritdoc} */ public function isFieldGranted(AclInterface $acl, $field, array $masks, array $sids, $administrativeMode = false) { try { try { $aces = $acl->getObjectFieldAces($field); if (!$aces) { throw new NoAceFoundException(); } return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode); } catch (NoAceFoundException $noObjectAces) { $aces = $acl->getClassFieldAces($field); if (!$aces) { throw $noObjectAces; } return $this->hasSufficientPermissions($acl, $aces, $masks, $sids, $administrativeMode); } } catch (NoAceFoundException $noClassAces) { if ($acl->isEntriesInheriting() && null !== ($parentAcl = $acl->getParentAcl())) { return $parentAcl->isFieldGranted($field, $masks, $sids, $administrativeMode); } throw $noClassAces; } }
/** * Installs the default Class Ace entries into the provided $acl object. * * Override this method in a subclass to change what permissions are defined. * Once this method has been overridden you need to run the * `fos_comment:installAces --flush` command * * @param AclInterface $acl * @param MaskBuilder $builder * @return void */ protected function doInstallFallbackAcl(AclInterface $acl, MaskBuilder $builder) { $builder->add('iddqd'); $acl->insertClassAce(new RoleSecurityIdentity('ROLE_SUPER_ADMIN'), $builder->get()); $builder->reset(); $builder->add('create'); $builder->add('view'); $acl->insertClassAce(new RoleSecurityIdentity('IS_AUTHENTICATED_ANONYMOUSLY'), $builder->get()); $builder->reset(); $builder->add('create'); $builder->add('view'); $acl->insertClassAce(new RoleSecurityIdentity('ROLE_USER'), $builder->get()); }
/** * {@inheritdoc} */ public function setParentAcl(AclInterface $acl = null) { if (null !== $acl && null === $acl->getId()) { throw new \InvalidArgumentException('$acl must have an ID.'); } if ($this->parentAcl !== $acl) { $this->onPropertyChanged('parentAcl', $this->parentAcl, $acl); $this->parentAcl = $acl; } }
/** * {@inheritdoc} */ public function findClassAceIndexByUsername(AclInterface $acl, $username) { foreach ($acl->getClassAces() as $index => $entry) { if ($entry->getSecurityIdentity() instanceof UserSecurityIdentity && $entry->getSecurityIdentity()->getUsername() === $username) { return $index; } } return false; }
/** * This regenerates the ancestor table which is used for fast read access. * * @param AclInterface $acl */ private function regenerateAncestorRelations(AclInterface $acl) { $pk = $acl->getId(); $this->connection->executeQuery($this->getDeleteObjectIdentityRelationsSql($pk)); $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $pk)); $parentAcl = $acl->getParentAcl(); while (null !== $parentAcl) { $this->connection->executeQuery($this->getInsertObjectIdentityRelationSql($pk, $parentAcl->getId())); $parentAcl = $parentAcl->getParentAcl(); } }
/** * Determines whether the ACE is applicable to the given permission/security identity combination. * * Strategy ALL: * The ACE will be considered applicable when all the turned-on bits in the * required mask are also turned-on in the ACE mask. * * Strategy ANY: * The ACE will be considered applicable when any of the turned-on bits in * the required mask is also turned-on the in the ACE mask. * * Strategy EQUAL: * The ACE will be considered applicable when the bitmasks are equal. * * @param integer $requiredMask * @param EntryInterface $ace * @param AclInterface $acl * @throws \RuntimeException if the ACE strategy is not supported * @return bool */ protected function isAceApplicable($requiredMask, EntryInterface $ace, AclInterface $acl) { $extension = $this->getContext()->getAclExtension(); $aceMask = $ace->getMask(); if ($acl->getObjectIdentity()->getType() === ObjectIdentityFactory::ROOT_IDENTITY_TYPE) { if ($acl->getObjectIdentity()->getIdentifier() !== $extension->getExtensionKey()) { return false; } $aceMask = $extension->adaptRootMask($aceMask, $this->getContext()->getObject()); } if ($extension->getServiceBits($requiredMask) !== $extension->getServiceBits($aceMask)) { return false; } $requiredMask = $extension->removeServiceBits($requiredMask); $aceMask = $extension->removeServiceBits($aceMask); $strategy = $ace->getStrategy(); switch ($strategy) { case self::ALL: return $requiredMask === ($aceMask & $requiredMask); case self::ANY: return 0 !== ($aceMask & $requiredMask); case self::EQUAL: return $requiredMask === $aceMask; default: throw new \RuntimeException(sprintf('The strategy "%s" is not supported.', $strategy)); } }
/** * This updates the parent and ancestors in the identity * * @param AclInterface $acl * @param array $changes * @return void */ protected function updateObjectIdentity(AclInterface $acl, array $changes) { if (isset($changes['entriesInheriting'])) { $updates['entriesInheriting'] = $changes['entriesInheriting'][1]; } if (isset($changes['parentAcl'])) { $query = array('_id' => new \MongoId($acl->getParentAcl()->getId())); $parent = $this->connection->selectCollection($this->options['oid_collection'])->findOne($query); $updates['parent'] = $parent; if (isset($parent['ancestors'])) { $ancestors = $parent['ancestors']; } $ancestors[] = $parent['_id']; $updates['ancestors'] = $ancestors; } if (!isset($updates)) { return; } $entry = array('_id' => new \MongoId($acl->getId())); $newData = array('$set' => $updates); $this->connection->selectCollection($this->options['oid_collection'])->update($entry, $newData); }
/** * @param SecurityIdentityInterface $securityIdentity * @param $mask * @param AclInterface $acl * @return $this */ protected function addMask(SecurityIdentityInterface $securityIdentity, $mask, AclInterface $acl) { $acl->insertObjectAce($securityIdentity, $mask); $this->aclProvider->updateAcl($acl); return $this; }
/** * Makes an authorization decision. * * The order of ACEs, and SIDs is significant; the order of permission masks * not so much. It is important to note that the more specific security * identities should be at the beginning of the SIDs array in order for this * strategy to produce intuitive authorization decisions. * * First, we will iterate over permissions, then over security identities. * For each combination of permission, and identity we will test the * available ACEs until we find one which is applicable. * * The first applicable ACE will make the ultimate decision for the * permission/identity combination. If it is granting, this method will return * true, if it is denying, the method will continue to check the next * permission/identity combination. * * This process is repeated until either a granting ACE is found, or no * permission/identity combinations are left. In the latter case, we will * call this method on the parent ACL if it exists, and isEntriesInheriting * is true. Otherwise, we will either throw an NoAceFoundException, or deny * access finally. * * @param AclInterface $acl * @param array $aces an array of ACE to check against * @param array $masks an array of permission masks * @param array $sids an array of SecurityIdentityInterface implementations * @param Boolean $administrativeMode true turns off audit logging * @return Boolean true, or false; either granting, or denying access respectively. */ protected function hasSufficientPermissions(AclInterface $acl, array $aces, array $masks, array $sids, $administrativeMode) { $firstRejectedAce = null; foreach ($masks as $requiredMask) { foreach ($sids as $sid) { if (!$acl->isSidLoaded($sid)) { throw new SidNotLoadedException(sprintf('The SID "%s" has not been loaded.', $sid)); } foreach ($aces as $ace) { if ($this->isAceApplicable($requiredMask, $sid, $ace)) { if ($ace->isGranting()) { if (!$administrativeMode && null !== $this->auditLogger) { $this->auditLogger->logIfNeeded(true, $ace); } return true; } if (null === $firstRejectedAce) { $firstRejectedAce = $ace; } break 2; } } } } if (null !== $firstRejectedAce) { if (!$administrativeMode && null !== $this->auditLogger) { $this->auditLogger->logIfNeeded(false, $firstRejectedAce); } return false; } throw new NoAceFoundException('No applicable ACE was found.'); }
/** * Get object ACE mask at specified index. * * @param AclInterface $acl The acl interface * @param int $index The index * * @return bool|int */ private function getMaskAtIndex(AclInterface $acl, $index) { $objectAces = $acl->getObjectAces(); /* @var $ace AuditableEntryInterface */ $ace = $objectAces[$index]; $securityIdentity = $ace->getSecurityIdentity(); if ($securityIdentity instanceof RoleSecurityIdentity) { return $ace->getMask(); } return false; }
/** * Extracts SIDs from ACL depending on entity config to prevent deletion of sharing when sharing scope is changed. * * @param AclInterface $acl * * @return array */ protected function extractSids(AclInterface $acl) { $sids = []; foreach ($acl->getObjectAces() as $key => $ace) { /** @var Entry $ace */ $sid = $ace->getSecurityIdentity(); if ($this->isSidApplicable($sid)) { $sids[$key] = $sid; } } return $sids; }