/**
  * @param \TYPO3\Flow\Mvc\Controller\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;
 }
 /**
  * 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('TYPO3.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();
 }
 /**
  * In live workspace this just renders a tag; for logged in users with access to the Backend this also adds required
  * attributes for the editing.
  *
  * @param string $property Name of the property to render. Note: If this tag has child nodes, they overrule this argument!
  * @param string $tag The name of the tag that should be wrapped around the property. By default this is a <div>
  * @param NodeInterface $node The node of the content element. Optional, will be resolved from the TypoScript context by default.
  * @return string The rendered property with a wrapping tag. In the user workspace this adds some required attributes for the RTE to work
  * @throws ViewHelperException
  */
 public function render($property, $tag = 'div', NodeInterface $node = null)
 {
     $this->tag->setTagName($tag);
     $this->tag->forceClosingTag(true);
     $content = $this->renderChildren();
     if ($node === null) {
         $node = $this->getNodeFromTypoScriptContext();
     }
     if ($node === null) {
         throw new ViewHelperException('A node is required, but one was not supplied and could not be found in the TypoScript context.', 1408521638);
     }
     if ($content === null) {
         if (!$this->templateVariableContainer->exists($property)) {
             throw new ViewHelperException(sprintf('The property "%1$s" was not set as a template variable. If you use this ViewHelper in a partial, make sure to pass the node property "%1$s" as an argument.', $property), 1384507046);
         }
         $content = $this->templateVariableContainer->get($property);
     }
     $this->tag->setContent($content);
     /** @var $contentContext ContentContext */
     $contentContext = $node->getContext();
     if ($contentContext->getWorkspaceName() === 'live' || !$this->privilegeManager->isPrivilegeTargetGranted('TYPO3.Neos:Backend.GeneralAccess')) {
         return $this->tag->render();
     }
     if (!$this->nodeAuthorizationService->isGrantedToEditNode($node)) {
         return $this->tag->render();
     }
     $this->tag->addAttribute('property', 'typo3:' . $property);
     $this->tag->addAttribute('class', $this->tag->hasAttribute('class') ? 'neos-inline-editable ' . $this->tag->getAttribute('class') : 'neos-inline-editable');
     return $this->tag->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'));
     $actualResult = $this->ifAccessViewHelper->render('somePrivilegeTarget');
     $this->assertEquals('ElseViewHelperResults', $actualResult);
 }
 /**
  * Shows the specified node and takes visibility and access restrictions into
  * account.
  *
  * @param NodeInterface $node
  * @return string View output for the specified node
  * @Flow\SkipCsrfProtection We need to skip CSRF protection here because this action could be called with unsafe requests from widgets or plugins that are rendered on the node - For those the CSRF token is validated on the sub-request, so it is safe to be skipped here
  * @Flow\IgnoreValidation("node")
  * @throws NodeNotFoundException
  */
 public function showAction(NodeInterface $node = NULL)
 {
     if ($node === NULL) {
         throw new NodeNotFoundException('The requested node does not exist or isn\'t accessible to the current user', 1430218623);
     }
     if (!$node->getContext()->isLive() && !$this->privilegeManager->isPrivilegeTargetGranted('TYPO3.Neos:Backend.GeneralAccess')) {
         $this->redirect('index', 'Login', NULL, array('unauthorized' => TRUE));
     }
     $inBackend = $node->getContext()->isInBackend();
     if ($node->getNodeType()->isOfType('TYPO3.Neos:Shortcut') && !$inBackend) {
         $this->handleShortcutNode($node);
     }
     $this->view->assign('value', $node);
     if ($inBackend) {
         $this->overrideViewVariablesFromInternalArguments();
         /** @var UserInterfaceMode $renderingMode */
         $renderingMode = $node->getContext()->getCurrentRenderingMode();
         $this->response->setHeader('Cache-Control', 'no-cache');
         if ($renderingMode !== NULL) {
             // Deprecated TypoScript context variable from version 2.0.
             $this->view->assign('editPreviewMode', $renderingMode->getTypoScriptPath());
         }
         if (!$this->view->canRenderWithNodeAndPath()) {
             $this->view->setTypoScriptPath('rawContent');
         }
     }
     if ($this->session->isStarted() && $inBackend) {
         $this->session->putData('lastVisitedNode', $node->getContextPath());
     }
 }
 /**
  * renders <f:then> child if access to the given resource is allowed, otherwise renders <f:else> child.
  *
  * @param string $privilegeTarget The Privilege target identifier
  * @param array $parameters optional privilege target parameters to be evaluated
  * @return string the rendered then/else child nodes depending on the access
  * @api
  */
 public function render($privilegeTarget, array $parameters = array())
 {
     if ($this->privilegeManager->isPrivilegeTargetGranted($privilegeTarget, $parameters)) {
         return $this->renderThenChild();
     } else {
         return $this->renderElseChild();
     }
 }
Esempio n. 7
0
 /**
  * Checks whether the current user has access to a module
  *
  * @param string $modulePath
  * @return boolean
  */
 public function isAllowed($moduleName)
 {
     $moduleConfiguration = $this->modules[$moduleName];
     if (isset($moduleConfiguration['privilegeTarget']) && !$this->privilegeManager->isPrivilegeTargetGranted($moduleConfiguration['privilegeTarget'])) {
         return true;
     }
     return false;
 }
 /**
  * @param NodeInterface $node
  * @return array
  */
 public function checkNodeForRoles(NodeInterface $node, array $roles)
 {
     $checkedNodes = [];
     foreach ($roles as $role) {
         /** @var Role $role */
         $checkedNodes[$role->getIdentifier()] = ['editNode' => $this->privilegeManager->isGrantedForRoles([$role], EditNodePrivilege::class, new NodePrivilegeSubject($node)), 'removeNode' => $this->privilegeManager->isGrantedForRoles([$role], RemoveNodePrivilege::class, new NodePrivilegeSubject($node)), 'createNodeOfType' => $this->privilegeManager->isGrantedForRoles([$role], CreateNodePrivilege::class, new CreateNodePrivilegeSubject($node)), 'showInTree' => $this->privilegeManager->isGrantedForRoles([$role], NodeTreePrivilege::class, new NodePrivilegeSubject($node))];
     }
     return $checkedNodes;
 }
 /**
  * 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('TYPO3.Neos:Backend.GeneralAccess')) {
         return $this->findModeByName('live');
     }
     /** @var \TYPO3\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('TYPO3.Neos:Backend.GeneralAccess') === false) {
         return '';
     }
     /** @var $actionRequest ActionRequest */
     $actionRequest = $this->controllerContext->getRequest();
     $innerView = new StandaloneView($actionRequest);
     $innerView->setTemplatePathAndFilename('resource://TYPO3.Neos/Private/Templates/Backend/Content/Container.html');
     $innerView->setFormat('html');
     $innerView->setPartialRootPath('resource://TYPO3.Neos/Private/Partials');
     $user = $this->securityContext->getPartyByType('TYPO3\\Neos\\Domain\\Model\\User');
     $innerView->assignMultiple(array('node' => $node, 'modules' => $this->menuHelper->buildModuleList($this->controllerContext), 'sites' => $this->menuHelper->buildSiteList($this->controllerContext), 'user' => $user));
     return $innerView->render();
 }
 /**
  * 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('TYPO3.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');
 }
 /**
  * Is access to the neos backend granted by current authentications.
  *
  * @return boolean
  */
 protected function hasAccessToBackend()
 {
     try {
         return $this->privilegeManager->isPrivilegeTargetGranted('TYPO3.Neos:Backend.GeneralAccess');
     } catch (\TYPO3\Flow\Security\Exception $exception) {
         return FALSE;
     }
 }
 /**
  * Is access to the neos backend granted by current authentications.
  *
  * @return boolean
  */
 protected function hasAccessToBackend()
 {
     try {
         return $this->privilegeManager->isPrivilegeTargetGranted('TYPO3.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('TYPO3.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>');
 }
 /**
  * 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('TYPO3.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;
 }
 /**
  * @test
  */
 public function renderDoesNotAddEditingMetaDataIfEditNodePrivilegeIsNotGranted()
 {
     $this->templateVariables = array('someProperty' => 'somePropertyValue');
     $this->mockContentContext->expects($this->atLeastOnce())->method('getWorkspaceName')->will($this->returnValue('not-live'));
     $this->mockPrivilegeManager->expects($this->atLeastOnce())->method('isPrivilegeTargetGranted')->with('TYPO3.Neos:Backend.GeneralAccess')->will($this->returnValue(true));
     $this->mockNodeAuthorizationService->expects($this->atLeastOnce())->method('isGrantedToEditNode')->will($this->returnValue(false));
     $this->tagBuilder->expects($this->never())->method('addAttribute');
     $this->injectDependenciesIntoViewHelper($this->editableViewHelper);
     $this->injectTypoScriptObject();
     $this->editableViewHelper->render('someProperty');
 }
 /**
  * Evaluate this TypoScript object and return the result
  *
  * @return mixed
  * @throws \TYPO3\Neos\Domain\Exception
  */
 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('TYPO3.Neos:Backend.GeneralAccess')) {
         return $content;
     }
     if ($node->isRemoved()) {
         $content = '';
     }
     return $this->contentElementWrappingService->wrapContentObject($node, $this->getContentElementTypoScriptPath(), $content, $this->tsValue('renderCurrentDocumentMetadata'));
 }
 /**
  * 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('TYPO3.Neos:Backend.GeneralAccess')) {
         return $content;
     }
     if ($node->isRemoved()) {
         $content = '';
     }
     return $this->contentElementEditableService->wrapContentProperty($node, $property, $content);
 }
 /**
  * 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 "TYPO3.Flow:Everybody".
         if ($this->privilegeManager->isGranted(\TYPO3\Flow\Security\Authorization\Privilege\Method\MethodPrivilegeInterface::class, $privilegeSubject, $reason) === FALSE) {
             throw new NoTokensAuthenticatedException($noTokensAuthenticatedException->getMessage() . chr(10) . $reason, $noTokensAuthenticatedException->getCode());
         }
     }
     if ($this->privilegeManager->isGranted(\TYPO3\Flow\Security\Authorization\Privilege\Method\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="\TYPO3\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, 'TYPO3.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 \TYPO3\TYPO3CR\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 === 'TYPO3.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));
         }
     }
 }
 /**
  * @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);
 }
 /**
  * Wrap the $content identified by $node with the needed markup for the backend.
  *
  * @param NodeInterface $node
  * @param string $typoScriptPath
  * @param string $content
  * @param boolean $renderCurrentDocumentMetadata When this flag is set we will render the global metadata for the current document
  * @return string
  */
 public function wrapContentObject(NodeInterface $node, $typoScriptPath, $content, $renderCurrentDocumentMetadata = false)
 {
     /** @var $contentContext ContentContext */
     $contentContext = $node->getContext();
     if ($contentContext->getWorkspaceName() === 'live' || !$this->privilegeManager->isPrivilegeTargetGranted('TYPO3.Neos:Backend.GeneralAccess')) {
         return $content;
     }
     $nodeType = $node->getNodeType();
     $attributes = array();
     $attributes['typeof'] = 'typo3:' . $nodeType->getName();
     $attributes['about'] = $node->getContextPath();
     $classNames = array();
     if ($renderCurrentDocumentMetadata === true) {
         $attributes['data-neos-site-name'] = $contentContext->getCurrentSite()->getName();
         $attributes['data-neos-site-node-context-path'] = $contentContext->getCurrentSiteNode()->getContextPath();
         // Add the workspace of the TYPO3CR context to the attributes
         $attributes['data-neos-context-workspace-name'] = $contentContext->getWorkspaceName();
         $attributes['data-neos-context-dimensions'] = json_encode($contentContext->getDimensions());
         if (!$this->nodeAuthorizationService->isGrantedToEditNode($node)) {
             $attributes['data-node-__read-only'] = 'true';
             $attributes['data-nodedatatype-__read-only'] = 'boolean';
         }
     } else {
         if (!$this->nodeAuthorizationService->isGrantedToEditNode($node)) {
             return $content;
         }
         if ($node->isRemoved()) {
             $classNames[] = 'neos-contentelement-removed';
         }
         if ($node->isHidden()) {
             $classNames[] = 'neos-contentelement-hidden';
         }
         if ($nodeType->isOfType('TYPO3.Neos:ContentCollection')) {
             $attributes['rel'] = 'typo3:content-collection';
             // This is needed since the backend relies on this class (should not be necessary)
             $classNames[] = 'neos-contentcollection';
         } else {
             $classNames[] = 'neos-contentelement';
         }
         $uiConfiguration = $nodeType->hasConfiguration('ui') ? $nodeType->getConfiguration('ui') : array();
         if (isset($uiConfiguration['inlineEditable']) && $uiConfiguration['inlineEditable'] !== true || !isset($uiConfiguration['inlineEditable']) && !$this->hasInlineEditableProperties($node)) {
             $classNames[] = 'neos-not-inline-editable';
         }
         $attributes['tabindex'] = 0;
     }
     if ($node instanceof Node && !$node->dimensionsAreMatchingTargetDimensionValues()) {
         $classNames[] = 'neos-contentelement-shine-through';
     }
     if (count($classNames) > 0) {
         $attributes['class'] = implode(' ', $classNames);
     }
     // Add the actual workspace of the node, the node identifier and the TypoScript path to the attributes
     $attributes['data-node-_identifier'] = $node->getIdentifier();
     $attributes['data-node-__workspace-name'] = $node->getWorkspace()->getName();
     $attributes['data-node-__typoscript-path'] = $typoScriptPath;
     // these properties are needed together with the current NodeType to evaluate Node Type Constraints
     // TODO: this can probably be greatly cleaned up once we do not use CreateJS or VIE anymore.
     if ($node->getParent()) {
         $attributes['data-node-__parent-node-type'] = $node->getParent()->getNodeType()->getName();
     }
     if ($node->isAutoCreated()) {
         $attributes['data-node-_name'] = $node->getName();
         $attributes['data-node-_is-autocreated'] = 'true';
     }
     if ($node->getParent() && $node->getParent()->isAutoCreated()) {
         $attributes['data-node-_parent-is-autocreated'] = 'true';
         // we shall only add these properties if the parent is actually auto-created; as the Node-Type-Switcher in the UI relies on that.
         $attributes['data-node-__parent-node-name'] = $node->getParent()->getName();
         $attributes['data-node-__grandparent-node-type'] = $node->getParent()->getParent()->getNodeType()->getName();
     }
     $attributes = $this->addNodePropertyAttributes($node, $attributes);
     return $this->htmlAugmenter->addAttributes($content, $attributes, 'div', array('typeof'));
 }
 /**
  * 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('TYPO3.Neos:Backend.Module.Management.Workspaces.ManageInternalWorkspaces');
 }
 /**
  * Disables authorization for the current test
  *
  * @return void
  * @api
  */
 protected function disableAuthorization()
 {
     $this->privilegeManager->setOverrideDecision(true);
 }