/** * Return true or false as to whether a given user can access an object * * @param DataObject $node * The object to check perms on * @param string $perm * The permission to check against * @param Member $member * The member to check - if not set, the current user is used * * @return type */ public function checkPerm(DataObject $node, $perm, $member = null) { // if the node doesn't use the extension, fall back to SS logic if (!$node->hasExtension('Restrictable')) { switch ($perm) { case 'View': return $node->canView($member); case 'Write': return $node->canEdit($member); default: return $node->can($perm, $member); } } if (!$node) { return false; } if (!$member) { $member = singleton('SecurityContext')->getMember(); } if (is_int($member)) { $member = DataObject::get_by_id('Member', $member); } if (Permission::check('ADMIN', 'any', $member)) { return true; } $permCache = $this->getCache(); /* @var $permCache Zend_Cache_Core */ $key = $this->permCacheKey($node, $perm); $userGrants = null; if ($key) { $userGrants = $permCache->load($key); if (count($userGrants)) { $userGrants = $this->sanitiseCacheData($userGrants); } } if ($member && $userGrants && isset($userGrants[$perm][$member->ID])) { return $userGrants[$perm][$member->ID]; } // okay, we need to build up all the info we have about the node for permissions $s = $this->realiseAllSources($node); if (!$userGrants) { $userGrants = array(); } if (!isset($userGrants[$perm])) { $userGrants[$perm] = array(); } $result = null; // if no member, just check public view $public = $this->checkPublicPerms($node, $perm); if ($public) { $result = true; } // can return immediately if (!$member) { return $result; } if (is_null($result)) { // see whether we're the owner, and if the perm we're checking is in that list if ($this->checkOwnerPerms($node, $perm, $member)) { $result = true; } } $accessAuthority = ''; $directGrant = null; $can = false; if (is_null($result)) { $filter = array('ItemID' => $node->ID, 'ItemType' => $node->class); $existing = DataList::create('AccessAuthority')->filter($filter); // get all access authorities for this object $gids = isset($this->groups[$member->ID]) ? $this->groups[$member->ID] : null; if (!$gids) { $groups = $member ? $member->Groups() : array(); $gids = array(); if ($groups && $groups->Count()) { $gids = $groups->map('ID', 'ID')->toArray(); } $this->groups[$member->ID] = $gids; } $can = false; $directGrant = 'NONE'; if ($existing && $existing->count()) { foreach ($existing as $access) { // check if this mentions the perm in question $perms = $access->Perms->getValues(); if ($perms) { if (!in_array($perm, $perms)) { continue; } } $grant = null; $authority = $access->getAuthority(); if ($authority instanceof Group) { if (isset($gids[$access->AuthorityID])) { $grant = $access->Grant; } } elseif ($authority instanceof Member) { if ($member->ID == $access->AuthorityID) { $grant = $access->Grant; } } else { // another mechanism that will require a lookup of members in a list // TODO cache this if ($authority instanceof ListOfMembers) { $listMembers = $authority->getAllMembers()->map('ID', 'Title'); if (isset($listMembers[$member->ID])) { $grant = $access->Grant; } } } if ($grant) { // if it's deny, we can just break away immediately, otherwise we need to evaluate all the // others in case there's another DENY in there somewhere if ($grant === 'DENY') { $directGrant = 'DENY'; // immediately break break; } else { // mark that it's been granted for now $directGrant = 'GRANT'; } } } } } // return immediately if we have something if ($directGrant === 'GRANT') { $result = true; } if ($directGrant === 'DENY') { $result = false; } // otherwise query our parents if (is_null($result) && $node->InheritPerms) { $permParents = $this->getEffectiveParents($node); if (count($permParents) || $permParents instanceof IteratorAggregate) { foreach ($permParents as $permParent) { if ($permParent && $this->checkPerm($permParent, $perm, $member)) { $result = true; } } } } if (is_null($result)) { $result = false; } $userGrants[$perm][$member->ID] = $result; if ($key) { $permCache->save($userGrants, $key); } return $result; }