/** * Handle an exception by displaying an error message inside the Neos backend, if logged in and not displaying the live workspace. * * @param array $typoScriptPath path causing the exception * @param \Exception $exception exception to handle * @param integer $referenceCode * @return string */ protected function handle($typoScriptPath, \Exception $exception, $referenceCode) { $handler = new ContextDependentHandler(); $handler->setRuntime($this->runtime); $output = $handler->handleRenderingException($typoScriptPath, $exception); $currentContext = $this->runtime->getCurrentContext(); /** @var NodeInterface $documentNode */ $documentNode = isset($currentContext['documentNode']) ? $currentContext['documentNode'] : null; /** @var NodeInterface $node */ $node = isset($currentContext['node']) ? $currentContext['node'] : null; $fluidView = $this->prepareFluidView(); $isBackend = false; /** @var NodeInterface $siteNode */ $siteNode = isset($currentContext['site']) ? $currentContext['site'] : null; if ($documentNode === null) { // Actually we cannot be sure that $node is a document. But for fallback purposes this should be safe. $documentNode = $siteNode ? $siteNode : $node; } if ($documentNode !== null && $documentNode->getContext()->getWorkspace()->getName() !== 'live' && $this->privilegeManager->isPrivilegeTargetGranted('Neos.Neos:Backend.GeneralAccess')) { $isBackend = true; $fluidView->assign('metaData', $this->contentElementWrappingService->wrapCurrentDocumentMetadata($documentNode, '<div id="neos-document-metadata"></div>', $typoScriptPath)); } $fluidView->assignMultiple(array('isBackend' => $isBackend, 'message' => $output, 'node' => $node)); return $fluidView->render(); }
/** * @test */ public function viewHelperRendersElseIfHasAccessToPrivilegeTargetReturnsFalse() { $this->mockPrivilegeManager->expects($this->once())->method('isPrivilegeTargetGranted')->with('somePrivilegeTarget')->will($this->returnValue(false)); $this->ifAccessViewHelper->expects($this->once())->method('renderElseChild')->will($this->returnValue('ElseViewHelperResults')); $arguments = ['privilegeTarget' => 'somePrivilegeTarget', 'parameters' => []]; $this->ifAccessViewHelper->setArguments($arguments); $actualResult = $this->ifAccessViewHelper->render(); $this->assertEquals('ElseViewHelperResults', $actualResult); }
/** * Get the current rendering mode (editPreviewMode). * Will return a live mode when not in backend. * * @return UserInterfaceMode */ public function findModeByCurrentUser() { if ($this->userService->getBackendUser() === null || !$this->privilegeManager->isPrivilegeTargetGranted('Neos.Neos:Backend.GeneralAccess')) { return $this->findModeByName('live'); } /** @var \Neos\Neos\Domain\Model\User $user */ $editPreviewMode = $this->userService->getUserPreference('contentEditing.editPreviewMode'); if ($editPreviewMode === null) { $editPreviewMode = $this->defaultEditPreviewMode; } $mode = $this->findModeByName($editPreviewMode); return $mode; }
/** * @param NodeInterface $node * @return string * @throws NeosException */ public function render(NodeInterface $node) { if ($this->privilegeManager->isPrivilegeTargetGranted('Neos.Neos:Backend.GeneralAccess') === false) { return ''; } /** @var $actionRequest ActionRequest */ $actionRequest = $this->controllerContext->getRequest(); $innerView = new StandaloneView($actionRequest); $innerView->setTemplatePathAndFilename('resource://Neos.Neos/Private/Templates/Backend/Content/Container.html'); $innerView->setFormat('html'); $innerView->setPartialRootPath('resource://Neos.Neos/Private/Partials'); $user = $this->partyService->getAssignedPartyOfAccount($this->securityContext->getAccount()); $innerView->assignMultiple(array('node' => $node, 'modules' => $this->menuHelper->buildModuleList($this->controllerContext), 'sites' => $this->menuHelper->buildSiteList($this->controllerContext), 'user' => $user)); return $innerView->render(); }
/** * @param ControllerContext $controllerContext * @return array */ public function buildModuleList(ControllerContext $controllerContext) { $modules = array(); foreach ($this->settings['modules'] as $module => $moduleConfiguration) { if (!$this->isModuleEnabled($module)) { continue; } if (isset($moduleConfiguration['privilegeTarget']) && !$this->privilegeManager->isPrivilegeTargetGranted($moduleConfiguration['privilegeTarget'])) { continue; } $submodules = array(); if (isset($moduleConfiguration['submodules'])) { foreach ($moduleConfiguration['submodules'] as $submodule => $submoduleConfiguration) { if (!$this->isModuleEnabled($module . '/' . $submodule)) { continue; } if (isset($submoduleConfiguration['privilegeTarget']) && !$this->privilegeManager->isPrivilegeTargetGranted($submoduleConfiguration['privilegeTarget'])) { continue; } $submodules[] = $this->collectModuleData($controllerContext, $submodule, $submoduleConfiguration, $module . '/' . $submodule); } } $modules[] = array_merge($this->collectModuleData($controllerContext, $module, $moduleConfiguration, $module), array('group' => $module, 'submodules' => $submodules)); } return $modules; }
/** * Wrap the $content identified by $node with the needed markup for the backend. * * @param NodeInterface $node * @param string $property * @param string $content * @return string */ public function wrapContentProperty(NodeInterface $node, $property, $content) { /** @var $contentContext ContentContext */ $contentContext = $node->getContext(); if ($contentContext->getWorkspaceName() === 'live' || !$this->privilegeManager->isPrivilegeTargetGranted('Neos.Neos:Backend.GeneralAccess')) { return $content; } if (!$this->nodeAuthorizationService->isGrantedToEditNode($node)) { return $content; } $attributes = array(); $attributes['class'] = 'neos-inline-editable'; $attributes['property'] = 'typo3:' . $property; $attributes['data-neos-node-type'] = $node->getNodeType()->getName(); return $this->htmlAugmenter->addAttributes($content, $attributes, 'span'); }
/** * renders the exception to nice html content element to display, edit, remove, ... * * @param string $typoScriptPath - path causing the exception * @param \Exception $exception - exception to handle * @param integer $referenceCode - might be unset * @return string */ protected function handle($typoScriptPath, \Exception $exception, $referenceCode) { $handler = new ContextDependentHandler(); $handler->setRuntime($this->runtime); $output = $handler->handleRenderingException($typoScriptPath, $exception); $currentContext = $this->getRuntime()->getCurrentContext(); if (isset($currentContext['node'])) { /** @var NodeInterface $node */ $node = $currentContext['node']; $applicationContext = $this->environment->getContext(); if ($applicationContext->isProduction() && $this->privilegeManager->isPrivilegeTargetGranted('Neos.Neos:Backend.GeneralAccess') && $node->getContext()->getWorkspaceName() !== 'live') { $output = '<div class="neos-rendering-exception"><div class="neos-rendering-exception-title">Failed to render element' . $output . '</div></div>'; } return $this->contentElementWrappingService->wrapContentObject($node, $output, $typoScriptPath); } return $output; }
/** * Is access to the neos backend granted by current authentications. * * @return boolean */ protected function hasAccessToBackend() { try { return $this->privilegeManager->isPrivilegeTargetGranted('Neos.Neos:Backend.GeneralAccess'); } catch (Exception $exception) { return false; } }
/** * @test */ public function wrapContentPropertyDoesNotAddEditingMetaDataIfEditNodePrivilegeIsNotGranted() { $this->mockContentContext->expects($this->atLeastOnce())->method('getWorkspaceName')->will($this->returnValue('not-live')); $this->mockPrivilegeManager->expects($this->atLeastOnce())->method('isPrivilegeTargetGranted')->with('Neos.Neos:Backend.GeneralAccess')->will($this->returnValue(true)); $this->mockNodeAuthorizationService->expects($this->atLeastOnce())->method('isGrantedToEditNode')->will($this->returnValue(false)); $this->mockHtmlAugmenter->expects($this->never())->method('addAttributes'); $this->contentElementEditableService->wrapContentProperty($this->mockNode, 'someProperty', '<div>someRenderedPropertyValue</div>'); }
/** * Evaluate this TypoScript object and return the result * * @return mixed */ public function evaluate() { $content = $this->getValue(); /** @var $node NodeInterface */ $node = $this->tsValue('node'); if (!$node instanceof NodeInterface) { return $content; } /** @var $property string */ $property = $this->tsValue('property'); /** @var $contentContext ContentContext */ $contentContext = $node->getContext(); if ($contentContext->getWorkspaceName() === 'live') { return $content; } if (!$this->privilegeManager->isPrivilegeTargetGranted('Neos.Neos:Backend.GeneralAccess')) { return $content; } if ($node->isRemoved()) { $content = ''; } return $this->contentElementEditableService->wrapContentProperty($node, $property, $content); }
/** * Evaluate this TypoScript object and return the result * * @return mixed */ public function evaluate() { $content = $this->getValue(); /** @var $node NodeInterface */ $node = $this->tsValue('node'); if (!$node instanceof NodeInterface) { return $content; } /** @var $contentContext ContentContext */ $contentContext = $node->getContext(); if ($contentContext->getWorkspaceName() === 'live') { return $content; } if (!$this->privilegeManager->isPrivilegeTargetGranted('Neos.Neos:Backend.GeneralAccess')) { return $content; } if ($node->isRemoved()) { $content = ''; } if ($this->tsValue('renderCurrentDocumentMetadata')) { return $this->contentElementWrappingService->wrapCurrentDocumentMetadata($node, $content, $this->getContentElementTypoScriptPath()); } return $this->contentElementWrappingService->wrapContentObject($node, $content, $this->getContentElementTypoScriptPath()); }
/** * Invokes the security interception * * @return boolean TRUE if the security checks was passed * @throws AccessDeniedException * @throws AuthenticationRequiredException if an entity could not be found (assuming it is bound to the current session), causing a redirect to the authentication entrypoint * @throws NoTokensAuthenticatedException if no tokens could be found and the accessDecisionManager denied access to the privilege target, causing a redirect to the authentication entrypoint */ public function invoke() { $reason = ''; $privilegeSubject = new MethodPrivilegeSubject($this->joinPoint); try { $this->authenticationManager->authenticate(); } catch (EntityNotFoundException $exception) { throw new AuthenticationRequiredException('Could not authenticate. Looks like a broken session.', 1358971444, $exception); } catch (NoTokensAuthenticatedException $noTokensAuthenticatedException) { // We still need to check if the privilege is available to "Neos.Flow:Everybody". if ($this->privilegeManager->isGranted(MethodPrivilegeInterface::class, $privilegeSubject, $reason) === false) { throw new NoTokensAuthenticatedException($noTokensAuthenticatedException->getMessage() . chr(10) . $reason, $noTokensAuthenticatedException->getCode()); } } if ($this->privilegeManager->isGranted(MethodPrivilegeInterface::class, $privilegeSubject, $reason) === false) { throw new AccessDeniedException($this->renderDecisionReasonMessage($reason), 1222268609); } }
/** * Update a given account * * @param Account $account The account to update * @param array $roleIdentifiers A possibly updated list of roles for the user's primary account * @param array $password Expects an array in the format array('<password>', '<password confirmation>') * @Flow\Validate(argumentName="password", type="\Neos\Neos\Validation\Validator\PasswordValidator", options={ "allowEmpty"=1, "minimum"=1, "maximum"=255 }) * @return void */ public function updateAccountAction(Account $account, array $roleIdentifiers, array $password = array()) { $user = $this->userService->getUser($account->getAccountIdentifier(), $account->getAuthenticationProviderName()); if ($user === $this->currentUser) { $roles = array(); foreach ($roleIdentifiers as $roleIdentifier) { $roles[$roleIdentifier] = $this->policyService->getRole($roleIdentifier); } if (!$this->privilegeManager->isPrivilegeTargetGrantedForRoles($roles, 'Neos.Neos:Backend.Module.Administration.Users')) { $this->addFlashMessage('With the selected roles the currently logged in user wouldn\'t have access to this module any longer. Please adjust the assigned roles!', 'Don\'t lock yourself out', Message::SEVERITY_WARNING, array(), 1416501197); $this->forward('edit', null, null, array('user' => $this->currentUser)); } } $password = array_shift($password); if (strlen(trim(strval($password))) > 0) { $this->userService->setUserPassword($user, $password); } $this->userService->setRolesForAccount($account, $roleIdentifiers); $this->addFlashMessage('The account has been updated.', 'Account updated', Message::SEVERITY_OK); $this->redirect('edit', null, null, array('user' => $user)); }
/** * Collect node data and traverse child nodes * * @param array &$nodes * @param NodeInterface $node * @param string $nodeTypeFilter * @param integer $depth levels of child nodes to fetch. 0 = unlimited * @param \Neos\ContentRepository\Domain\Model\NodeInterface $untilNode if given, expand all nodes on the rootline towards $untilNode, no matter what is defined with $depth. * @param integer $recursionPointer current recursion level * @return void */ protected function collectChildNodeData(array &$nodes, NodeInterface $node, $nodeTypeFilter, $depth = 0, NodeInterface $untilNode = null, $recursionPointer = 1) { foreach ($node->getChildNodes($nodeTypeFilter) as $childNode) { if (!$this->privilegeManager->isGranted(NodeTreePrivilege::class, new NodePrivilegeSubject($childNode))) { continue; } /** @var NodeInterface $childNode */ $expand = $depth === 0 || $recursionPointer < $depth; if ($expand === false && $untilNode !== null && strpos($untilNode->getPath(), $childNode->getPath()) === 0 && $childNode !== $untilNode) { // in case $untilNode is set, and the current childNode is on the rootline of $untilNode (and not the node itself), expand the node. $expand = true; } switch ($this->outputStyle) { case self::STYLE_LIST: $nodeType = $childNode->getNodeType()->getName(); $properties = $childNode->getProperties(); $properties['__contextNodePath'] = $childNode->getContextPath(); $properties['__workspaceName'] = $childNode->getWorkspace()->getName(); $properties['__nodeName'] = $childNode->getName(); $properties['__nodeType'] = $nodeType; $properties['__title'] = $nodeType === 'Neos.Neos:Document' ? $childNode->getProperty('title') : $childNode->getLabel(); array_push($nodes, $properties); if ($expand) { $this->collectChildNodeData($nodes, $childNode, $nodeTypeFilter, $depth, $untilNode, $recursionPointer + 1); } break; case self::STYLE_TREE: $children = array(); $hasChildNodes = $childNode->hasChildNodes($nodeTypeFilter) === true; if ($expand && $hasChildNodes) { $this->collectChildNodeData($children, $childNode, $nodeTypeFilter, $depth, $untilNode, $recursionPointer + 1); } array_push($nodes, $this->collectTreeNodeData($childNode, $expand, $children, $hasChildNodes)); } } }
/** * Disables authorization for the current test * * @return void * @api */ protected function disableAuthorization() { $this->privilegeManager->setOverrideDecision(true); }
/** * Checks if the current user may transfer ownership of the given workspace * * In future versions, this logic may be implemented in Neos in a more generic way (for example, by means of an * ACL object), but for now, this method exists in order to at least centralize and encapsulate the required logic. * * @param Workspace $workspace The workspace * @return boolean */ public function currentUserCanTransferOwnershipOfWorkspace(Workspace $workspace) { if ($workspace->isPersonalWorkspace()) { return false; } // The privilege to manage shared workspaces is needed, because regular editors should not change ownerships // of their internal workspaces, even if it was technically possible, because they wouldn't be able to change // ownership back to themselves. return $this->privilegeManager->isPrivilegeTargetGranted('Neos.Neos:Backend.Module.Management.Workspaces.ManageInternalWorkspaces'); }
/** * @param NodeInterface $node * @param string $propertyName * @return boolean */ public function isGrantedToEditNodeProperty(NodeInterface $node, $propertyName) { $privilegeSubject = new PropertyAwareNodePrivilegeSubject($node, null, $propertyName); return $this->privilegeManager->isGranted(EditNodePropertyPrivilege::class, $privilegeSubject); }