/** * Returns the vote for the given parameters. * Checks if user has access to a given action on a given value object. * * $attributes->limitations is a hash that contains: * - 'valueObject' - The ValueObject to check access on (eZ\Publish\API\Repository\Values\ValueObject). e.g. Location or Content. * - 'targets' - The location, parent or "assignment" value object, or an array of the same. * * This method must return one of the following constants: * ACCESS_GRANTED, ACCESS_DENIED, or ACCESS_ABSTAIN. * * @see \eZ\Publish\API\Repository\Repository::canUser() * * @param TokenInterface $token A TokenInterface instance * @param object $object The object to secure * @param array $attributes An array of attributes associated with the method being invoked * * @return integer either ACCESS_GRANTED, ACCESS_ABSTAIN, or ACCESS_DENIED */ public function vote(TokenInterface $token, $object, array $attributes) { foreach ($attributes as $attribute) { if ($this->supportsAttribute($attribute)) { $targets = isset($attribute->limitations['targets']) ? $attribute->limitations['targets'] : null; if ($this->repository->canUser($attribute->module, $attribute->function, $attribute->limitations['valueObject'], $targets) === false) { return VoterInterface::ACCESS_DENIED; } return VoterInterface::ACCESS_GRANTED; } } return VoterInterface::ACCESS_ABSTAIN; }
/** * removes a role from the given user. * * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to remove a role * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the role is not assigned to the user * * @param \eZ\Publish\API\Repository\Values\User\Role $role * @param \eZ\Publish\API\Repository\Values\User\User $user */ public function unassignRoleFromUser(APIRole $role, User $user) { if ($this->repository->canUser('role', 'assign', $user, $role) !== true) { throw new UnauthorizedException('role', 'assign'); } $spiRoleAssignments = $this->userHandler->loadRoleAssignmentsByGroupId($user->id); $isAssigned = false; foreach ($spiRoleAssignments as $spiRoleAssignment) { if ($spiRoleAssignment->roleId === $role->id) { $isAssigned = true; break; } } if (!$isAssigned) { throw new InvalidArgumentException("\$user", "Role is not assigned to the given User"); } $this->repository->beginTransaction(); try { $this->userHandler->unAssignRole($user->id, $role->id); $this->repository->commit(); } catch (Exception $e) { $this->repository->rollback(); throw $e; } }
/** * Loads the user groups the user belongs to * * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed read the user or user group * * @param \eZ\Publish\API\Repository\Values\User\User $user * @param int $offset the start offset for paging * @param int $limit the number of user groups returned * * @return \eZ\Publish\API\Repository\Values\User\UserGroup[] */ public function loadUserGroupsOfUser(APIUser $user, $offset = 0, $limit = 10) { $locationService = $this->repository->getLocationService(); if (!$this->repository->canUser('content', 'read', $user)) { throw new UnauthorizedException('content', 'read'); } $userLocations = $locationService->loadLocations($user->getVersionInfo()->getContentInfo()); $parentLocationIds = array(); foreach ($userLocations as $userLocation) { if ($userLocation->parentLocationId !== null) { $parentLocationIds[] = $userLocation->parentLocationId; } } $searchQuery = new Query(); $searchQuery->offset = $offset; $searchQuery->limit = $limit; $searchQuery->performCount = false; $searchQuery->filter = new CriterionLogicalAnd(array(new CriterionContentTypeId($this->settings['userGroupClassID']), new CriterionLocationId($parentLocationIds))); $searchResult = $this->repository->getSearchService()->findContent($searchQuery, array()); $userGroups = array(); foreach ($searchResult->searchHits as $resultItem) { $userGroups[] = $this->buildDomainUserGroupObject($resultItem->valueObject); } return $userGroups; }
/** * Indicates if the current user is allowed to perform an action given by the function on the given * objects. * * @param string $module The module, aka controller identifier to check permissions on * @param string $function The function, aka the controller action to check permissions on * @param \eZ\Publish\API\Repository\Values\ValueObject $object The object to check if the user has access to * @param mixed $targets The location, parent or "assignment" value object, or an array of the same * * @return bool */ public function canUser($module, $function, ValueObject $object, $targets = null) { $permissionSets = $this->hasAccess($module, $function); if ($permissionSets === false || $permissionSets === true) { return $permissionSets; } return $this->repository->canUser($module, $function, $object, $targets); }
/** * Process embed tags for a single tag type (embed or embed-inline) * @param \DOMDocument $xmlDoc * @param $tagName string name of the tag to extract */ protected function processTag(DOMDocument $xmlDoc, $tagName) { /** @var $embed \DOMElement */ foreach ($xmlDoc->getElementsByTagName($tagName) as $embed) { if (!($view = $embed->getAttribute("view"))) { $view = $tagName; } $embedContent = null; $parameters = $this->getParameters($embed); if ($contentId = $embed->getAttribute("object_id")) { try { /** @var \eZ\Publish\API\Repository\Values\Content\Content $content */ $content = $this->repository->sudo(function (Repository $repository) use($contentId) { return $repository->getContentService()->loadContent($contentId); }); if (!$this->repository->canUser('content', 'read', $content) && !$this->repository->canUser('content', 'view_embed', $content)) { throw new UnauthorizedException('content', 'read', array('contentId' => $contentId)); } // Check published status of the Content if ($content->getVersionInfo()->status !== APIVersionInfo::STATUS_PUBLISHED && !$this->repository->canUser('content', 'versionread', $content)) { throw new UnauthorizedException('content', 'versionread', array('contentId' => $contentId)); } $embedContent = $this->fragmentHandler->render(new ControllerReference('ez_content:embedContent', array('contentId' => $contentId, 'viewType' => $view, 'layout' => false, 'params' => $parameters))); } catch (APINotFoundException $e) { if ($this->logger) { $this->logger->error("While generating embed for xmltext, could not locate " . "Content object with ID " . $contentId); } } } else { if ($locationId = $embed->getAttribute("node_id")) { try { /** @var \eZ\Publish\API\Repository\Values\Content\Location $location */ $location = $this->repository->sudo(function (Repository $repository) use($locationId) { return $repository->getLocationService()->loadLocation($locationId); }); if (!$this->repository->canUser('content', 'read', $location->getContentInfo(), $location) && !$this->repository->canUser('content', 'view_embed', $location->getContentInfo(), $location)) { throw new UnauthorizedException('content', 'read', array('locationId' => $location->id)); } $embedContent = $this->fragmentHandler->render(new ControllerReference('ez_content:embedLocation', array('locationId' => $locationId, 'viewType' => $view, 'layout' => false, 'params' => $parameters))); } catch (APINotFoundException $e) { if ($this->logger) { $this->logger->error("While generating embed for xmltext, could not locate " . "Location with ID " . $locationId); } } } } if ($embedContent === null) { // Remove empty embed $embed->parentNode->removeChild($embed); } else { $embed->appendChild($xmlDoc->createCDATASection($embedContent)); } } }
/** * Creates the new tag. * * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user is not allowed to create this tag * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If the remote ID already exists * * @param \Netgen\TagsBundle\API\Repository\Values\Tags\TagCreateStruct $tagCreateStruct * * @return \Netgen\TagsBundle\API\Repository\Values\Tags\Tag The newly created tag */ public function createTag(TagCreateStruct $tagCreateStruct) { $keywords = $tagCreateStruct->getKeywords(); if (!empty($tagCreateStruct->parentTagId)) { if ($this->repository->canUser('tags', 'add', $this->loadTag($tagCreateStruct->parentTagId)) !== true) { throw new UnauthorizedException('tags', 'add'); } } elseif ($this->repository->hasAccess('tags', 'add') !== true) { throw new UnauthorizedException('tags', 'add'); } if (empty($tagCreateStruct->mainLanguageCode) || !is_string($tagCreateStruct->mainLanguageCode)) { throw new InvalidArgumentValue('mainLanguageCode', $tagCreateStruct->mainLanguageCode, 'TagCreateStruct'); } if (empty($keywords) || !is_array($keywords)) { throw new InvalidArgumentValue('keywords', $keywords, 'TagCreateStruct'); } if (!isset($keywords[$tagCreateStruct->mainLanguageCode])) { throw new InvalidArgumentValue('keywords', $keywords, 'TagCreateStruct'); } if ($tagCreateStruct->remoteId !== null && (empty($tagCreateStruct->remoteId) || !is_string($tagCreateStruct->remoteId))) { throw new InvalidArgumentValue('remoteId', $tagCreateStruct->remoteId, 'TagCreateStruct'); } // check for existence of tag with provided remote ID if ($tagCreateStruct->remoteId !== null) { try { $this->tagsHandler->loadTagInfoByRemoteId($tagCreateStruct->remoteId); throw new InvalidArgumentException('tagCreateStruct', 'Tag with provided remote ID already exists'); } catch (NotFoundException $e) { // Do nothing } } else { $tagCreateStruct->remoteId = md5(uniqid(get_class($this), true)); } if (!is_bool($tagCreateStruct->alwaysAvailable)) { throw new InvalidArgumentValue('alwaysAvailable', $tagCreateStruct->alwaysAvailable, 'TagCreateStruct'); } $createStruct = new CreateStruct(); $createStruct->parentTagId = !empty($tagCreateStruct->parentTagId) ? $tagCreateStruct->parentTagId : 0; $createStruct->mainLanguageCode = $tagCreateStruct->mainLanguageCode; $createStruct->keywords = $keywords; $createStruct->remoteId = $tagCreateStruct->remoteId; $createStruct->alwaysAvailable = $tagCreateStruct->alwaysAvailable; $this->repository->beginTransaction(); try { $newTag = $this->tagsHandler->create($createStruct); $this->repository->commit(); } catch (Exception $e) { $this->repository->rollback(); throw $e; } return $this->buildTagDomainObject($newTag); }
/** * Removes the given role assignment. * * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the authenticated user is not allowed to remove a role assignment * * @param \eZ\Publish\API\Repository\Values\User\RoleAssignment $roleAssignment */ public function removeRoleAssignment(RoleAssignment $roleAssignment) { if ($this->repository->canUser('role', 'assign', $roleAssignment) !== true) { throw new UnauthorizedException('role', 'assign'); } $spiRoleAssignment = $this->userHandler->loadRoleAssignment($roleAssignment->id); $this->repository->beginTransaction(); try { $this->userHandler->removeRoleAssignment($spiRoleAssignment->id); $this->repository->commit(); } catch (Exception $e) { $this->repository->rollback(); throw $e; } }
/** * Deletes $section from content repository * * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If the specified section is not found * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user is not allowed to delete a section * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException If section can not be deleted * because it is still assigned to some contents. * * @param \eZ\Publish\API\Repository\Values\Content\Section $section */ public function deleteSection(Section $section) { $loadedSection = $this->loadSection($section->id); if ($this->repository->canUser('section', 'edit', $loadedSection) !== true) { throw new UnauthorizedException('section', 'edit', array('name' => $loadedSection->name)); } if ($this->countAssignedContents($loadedSection) > 0) { throw new BadStateException("section", 'section is still assigned to content'); } $this->repository->beginTransaction(); try { $this->sectionHandler->delete($loadedSection->id); $this->repository->commit(); } catch (Exception $e) { $this->repository->rollback(); throw $e; } }
/** * Sets the object-state of a state group to $state for the given content. * * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException if the object state does not belong to the given group * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to change the object state * * @param \eZ\Publish\API\Repository\Values\Content\ContentInfo $contentInfo * @param \eZ\Publish\API\Repository\Values\ObjectState\ObjectStateGroup $objectStateGroup * @param \eZ\Publish\API\Repository\Values\ObjectState\ObjectState $objectState */ public function setContentState(ContentInfo $contentInfo, APIObjectStateGroup $objectStateGroup, APIObjectState $objectState) { if ($this->repository->canUser('state', 'assign', $contentInfo, $objectState) !== true) { throw new UnauthorizedException('state', 'assign', array('contentId' => $contentInfo->id)); } $loadedObjectState = $this->loadObjectState($objectState->id); if ($loadedObjectState->getObjectStateGroup()->id != $objectStateGroup->id) { throw new InvalidArgumentException('objectState', 'Object state does not belong to the given group'); } $this->repository->beginTransaction(); try { $this->objectStateHandler->setContentState($contentInfo->id, $objectStateGroup->id, $loadedObjectState->id); $this->repository->commit(); } catch (Exception $e) { $this->repository->rollback(); throw $e; } }
/** * Sends $location and all its children to trash and returns the corresponding trash item. * * Content is left untouched. * * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException if the user is not allowed to trash the given location * * @param \eZ\Publish\API\Repository\Values\Content\Location $location * * @return null|\eZ\Publish\API\Repository\Values\Content\TrashItem null if location was deleted, otherwise TrashItem */ public function trash(Location $location) { if (!is_numeric($location->id)) { throw new InvalidArgumentValue("id", $location->id, "Location"); } if ($this->repository->canUser('content', 'manage_locations', $location->getContentInfo(), $location) !== true) { throw new UnauthorizedException('content', 'manage_locations'); } $this->repository->beginTransaction(); try { $spiTrashItem = $this->persistenceHandler->trashHandler()->trashSubtree($location->id); $this->persistenceHandler->urlAliasHandler()->locationDeleted($location->id); $this->repository->commit(); } catch (Exception $e) { $this->repository->rollback(); throw $e; } return isset($spiTrashItem) ? $this->buildDomainTrashItemObject($spiTrashItem) : null; }
/** * Deletes $section from content repository. * * @throws \eZ\Publish\API\Repository\Exceptions\NotFoundException If the specified section is not found * @throws \eZ\Publish\API\Repository\Exceptions\UnauthorizedException If the current user is not allowed to delete a section * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException If section can not be deleted * because it is still assigned to some contents, * or because it is still being used in policy limitations. * * @param \eZ\Publish\API\Repository\Values\Content\Section $section */ public function deleteSection(Section $section) { $loadedSection = $this->loadSection($section->id); if ($this->repository->canUser('section', 'edit', $loadedSection) !== true) { throw new UnauthorizedException('section', 'edit', array('sectionId' => $loadedSection->id)); } if ($this->sectionHandler->assignmentsCount($loadedSection->id) > 0) { throw new BadStateException('section', 'section is still assigned to content'); } if ($this->sectionHandler->policiesCount($loadedSection->id) > 0) { throw new BadStateException('section', 'section is still being used in policy limitations'); } $this->repository->beginTransaction(); try { $this->sectionHandler->delete($loadedSection->id); $this->repository->commit(); } catch (Exception $e) { $this->repository->rollback(); throw $e; } }
/** * Process embed tags for a single tag type (embed or embed-inline) * @param \DOMDocument $xmlDoc * @param $tagName string name of the tag to extract */ protected function processTag(DOMDocument $xmlDoc, $tagName) { /** @var $embed \DOMElement */ foreach ($xmlDoc->getElementsByTagName($tagName) as $embed) { if (!($view = $embed->getAttribute("view"))) { $view = $tagName; } $embedContent = null; $parameters = array("noLayout" => true, "objectParameters" => array()); foreach ($embed->attributes as $attribute) { // We only consider tags in the custom namespace, and skip disallowed names if (!isset($this->excludedAttributes[$attribute->localName])) { $parameters["objectParameters"][$attribute->localName] = $attribute->nodeValue; } } if ($contentId = $embed->getAttribute("object_id")) { /** @var \eZ\Publish\API\Repository\Values\Content\Content $content */ $content = $this->repository->sudo(function (Repository $repository) use($contentId) { return $repository->getContentService()->loadContent($contentId); }); if (!$this->repository->canUser('content', 'read', $content) && !$this->repository->canUser('content', 'view_embed', $content)) { throw new UnauthorizedException('content', 'read'); } // Check published status of the Content if ($content->getVersionInfo()->status !== APIVersionInfo::STATUS_PUBLISHED && !$this->repository->canUser('content', 'versionread', $content)) { throw new UnauthorizedException('content', 'versionread'); } $embedContent = $this->viewManager->renderContent($content, $view, $parameters); } else { if ($locationId = $embed->getAttribute("node_id")) { /** @var \eZ\Publish\API\Repository\Values\Content\Location $location */ $location = $this->repository->sudo(function (Repository $repository) use($locationId) { return $repository->getLocationService()->loadLocation($locationId); }); if (!$this->repository->canUser('content', 'read', $location->getContentInfo(), $location) && !$this->repository->canUser('content', 'view_embed', $location->getContentInfo(), $location)) { throw new UnauthorizedException('content', 'read'); } $embedContent = $this->viewManager->renderLocation($location, $view, $parameters); } } if ($embedContent !== null) { $embed->appendChild($xmlDoc->createCDATASection($embedContent)); } } }
/** * Check if user has access to a given action on a given value object * * Indicates if the current user is allowed to perform an action given by the function on the given * objects. * * @throws \eZ\Publish\API\Repository\Exceptions\InvalidArgumentException If any of the arguments are invalid * @throws \eZ\Publish\API\Repository\Exceptions\BadStateException If value of the LimitationValue is unsupported * * @param string $module The module, aka controller identifier to check permissions on * @param string $function The function, aka the controller action to check permissions on * @param \eZ\Publish\API\Repository\Values\ValueObject $object The object to check if the user has access to * @param mixed $targets The location, parent or "assignment" value object, or an array of the same * * @return boolean */ public function canUser($module, $function, ValueObject $object, $targets = null) { return $this->repository->canUser($module, $function, $object, $targets); }
/** * Process embed tags for a single tag type (embed or embed-inline) * @param \DOMDocument $xmlDoc * @param $tagName string name of the tag to extract */ protected function processTag(DOMDocument $xmlDoc, $tagName) { /** @var $embed \DOMElement */ foreach ($xmlDoc->getElementsByTagName($tagName) as $embed) { if (!($view = $embed->getAttribute("view"))) { $view = $tagName; } $embedContent = null; $parameters = array("noLayout" => true, "objectParameters" => array()); foreach ($embed->attributes as $attribute) { // We only consider tags in the custom namespace, and skip disallowed names if (!isset($this->excludedAttributes[$attribute->localName])) { $parameters["objectParameters"][$attribute->localName] = $attribute->nodeValue; } } if ($contentId = $embed->getAttribute("object_id")) { try { /** @var \eZ\Publish\API\Repository\Values\Content\Content $content */ $content = $this->repository->sudo(function (Repository $repository) use($contentId) { return $repository->getContentService()->loadContent($contentId); }); if (!$this->repository->canUser('content', 'read', $content) && !$this->repository->canUser('content', 'view_embed', $content)) { throw new UnauthorizedException('content', 'read', array('contentId' => $contentId)); } // Check published status of the Content if ($content->getVersionInfo()->status !== APIVersionInfo::STATUS_PUBLISHED && !$this->repository->canUser('content', 'versionread', $content)) { throw new UnauthorizedException('content', 'versionread', array('contentId' => $contentId)); } $embedContent = $this->fragmentHandler->render(new ControllerReference('ez_content:embedContent', array('contentId' => $contentId, 'viewType' => $view, 'layout' => false, 'params' => $parameters))); } catch (APINotFoundException $e) { if ($this->logger) { $this->logger->error("While generating embed for xmltext, could not locate " . "Content object with ID " . $contentId); } } } else { if ($locationId = $embed->getAttribute("node_id")) { try { /** @var \eZ\Publish\API\Repository\Values\Content\Location $location */ $location = $this->repository->sudo(function (Repository $repository) use($locationId) { return $repository->getLocationService()->loadLocation($locationId); }); if (!$this->repository->canUser('content', 'read', $location->getContentInfo(), $location) && !$this->repository->canUser('content', 'view_embed', $location->getContentInfo(), $location)) { throw new UnauthorizedException('content', 'read', array('locationId' => $location->id)); } $embedContent = $this->fragmentHandler->render(new ControllerReference('ez_content:embedLocation', array('locationId' => $locationId, 'viewType' => $view, 'layout' => false, 'params' => $parameters))); } catch (APINotFoundException $e) { if ($this->logger) { $this->logger->error("While generating embed for xmltext, could not locate " . "Location with ID " . $locationId); } } } } if ($embedContent === null) { // Remove tmp paragraph if ($embed->parentNode->lookupNamespaceUri('tmp') !== null) { $embed->parentNode->parentNode->removeChild($embed->parentNode); } else { if ($embed->parentNode->localName === "link" && $embed->parentNode->childNodes->length === 1) { // Remove paragraph with empty link if ($embed->parentNode->parentNode->localName === "paragraph" && $embed->parentNode->parentNode->childNodes->length === 1) { $embed->parentNode->parentNode->parentNode->removeChild($embed->parentNode->parentNode); } else { $embed->parentNode->parentNode->removeChild($embed->parentNode); } } else { $embed->parentNode->removeChild($embed); } } } else { $embed->appendChild($xmlDoc->createCDATASection($embedContent)); } } }