diff --git a/Neos.Media.Browser/Classes/Controller/UsageController.php b/Neos.Media.Browser/Classes/Controller/UsageController.php index 76703174097..cbc866087c8 100644 --- a/Neos.Media.Browser/Classes/Controller/UsageController.php +++ b/Neos.Media.Browser/Classes/Controller/UsageController.php @@ -20,6 +20,8 @@ use Neos\Eel\FlowQuery\FlowQuery; use Neos\Flow\Annotations as Flow; use Neos\Flow\Mvc\Controller\ActionController; +use Neos\Flow\Security\Authorization\PrivilegeManagerInterface; +use Neos\Flow\Security\Context; use Neos\Media\Domain\Model\AssetInterface; use Neos\Media\Domain\Service\AssetService; use Neos\Neos\Controller\CreateContentContextTrait; @@ -80,6 +82,18 @@ class UsageController extends ActionController */ protected $domainUserService; + /** + * @Flow\Inject + * @var Context + */ + protected $securityContext; + + /** + * @Flow\Inject + * @var PrivilegeManagerInterface + */ + protected $privilegeManager; + /** * Get Related Nodes for an asset * @@ -116,6 +130,7 @@ public function relatedNodesAction(AssetInterface $asset) $workspace = $this->workspaceRepository->findByIdentifier($usage->getWorkspaceName()); $accessible = $this->domainUserService->currentUserCanReadWorkspace($workspace); + $inaccessibleRelation['label'] = $this->getLabelForInaccessibleWorkspace($workspace); $inaccessibleRelation['nodeIdentifier'] = $usage->getNodeIdentifier(); $inaccessibleRelation['workspaceName'] = $usage->getWorkspaceName(); $inaccessibleRelation['workspace'] = $workspace; @@ -165,7 +180,7 @@ public function relatedNodesAction(AssetInterface $asset) 'inaccessibleRelations' => $inaccessibleRelations, 'relatedNodes' => $relatedNodes, 'contentDimensions' => $this->contentDimensionPresetSource->getAllPresets(), - 'userWorkspace' => $userWorkspace + 'userWorkspace' => $userWorkspace, ]); } @@ -175,13 +190,28 @@ public function relatedNodesAction(AssetInterface $asset) */ private function getNodeFrom(AssetUsageInNodeProperties $assetUsage) { - $context = $this->_contextFactory->create( - [ + $context = $this->_contextFactory->create([ 'workspaceName' => $assetUsage->getWorkspaceName(), 'dimensions' => $assetUsage->getDimensionValues(), 'invisibleContentShown' => true, - 'removedContentShown' => true] - ); + 'removedContentShown' => true + ]); return $context->getNodeByIdentifier($assetUsage->getNodeIdentifier()); } + + private function getLabelForInaccessibleWorkspace(Workspace $workspace): string + { + $currentAccount = $this->securityContext->getAccount(); + + if ($currentAccount != null && $this->privilegeManager->isPrivilegeTargetGranted('Neos.Media.Browser:WorkspaceName')) { + if ($workspace->isPrivateWorkspace()) { + $owner = $workspace->getOwner(); + return '(' . $owner->getLabel() . ')'; + } else { + return '(' . $workspace->getTitle() . ')'; + } + } + + return ''; + } } diff --git a/Neos.Media.Browser/Configuration/Policy.yaml b/Neos.Media.Browser/Configuration/Policy.yaml index a237114296c..19058da9497 100644 --- a/Neos.Media.Browser/Configuration/Policy.yaml +++ b/Neos.Media.Browser/Configuration/Policy.yaml @@ -28,6 +28,12 @@ privilegeTargets: label: Allowed to replace asset resources matcher: 'method(Neos\Media\Browser\Controller\(Asset|Image)Controller->(replaceAssetResource|updateAssetResource)Action())' + # We evaluate the WorkspaceName privilegeTarget in code (UsageController) to determine whether we should show workspace names or not. + # To control access to the module in general, Neos.Media.Browser:AssetUsage is used (so that's why they have the same matcher string). + 'Neos.Media.Browser:WorkspaceName': + label: Allowed to see workspace owner + matcher: 'method(Neos\Media\Browser\Controller\UsageController->relatedNodesAction())' + roles: 'Neos.Neos:AbstractEditor': privileges: @@ -55,6 +61,9 @@ roles: - privilegeTarget: 'Neos.Media.Browser:ManageAssetCollections' permission: GRANT + - + privilegeTarget: 'Neos.Media.Browser:WorkspaceName' + permission: GRANT 'Neos.Flow:Everybody': privileges: diff --git a/Neos.Media.Browser/Resources/Private/Templates/Usage/RelatedNodes.html b/Neos.Media.Browser/Resources/Private/Templates/Usage/RelatedNodes.html index 8dde5d9cb3a..5d9f6345885 100644 --- a/Neos.Media.Browser/Resources/Private/Templates/Usage/RelatedNodes.html +++ b/Neos.Media.Browser/Resources/Private/Templates/Usage/RelatedNodes.html @@ -39,6 +39,7 @@ title="{neos:backend.translate(id: 'workspaces.personalWorkspace', source: 'Modules', package: 'Neos.Neos')}" data-neos-toggle="tooltip"> {neos:backend.translate(id: 'workspaces.personalWorkspace', source: 'Modules', package: 'Neos.Neos')} + {inaccessibleRelation.label} {neos:backend.translate(id: 'workspaces.privateWorkspace', source: 'Modules', package: 'Neos.Neos')} + {inaccessibleRelation.label} {neos:backend.translate(id: 'workspaces.internalWorkspace', source: 'Modules', package: 'Neos.Neos')} + {inaccessibleRelation.label} --- diff --git a/Neos.Neos/Configuration/Policy.yaml b/Neos.Neos/Configuration/Policy.yaml index 004c42eee77..16558e14c01 100644 --- a/Neos.Neos/Configuration/Policy.yaml +++ b/Neos.Neos/Configuration/Policy.yaml @@ -325,7 +325,6 @@ roles: 'Neos.Neos:Administrator': label: Neos Administrator description: Grants access to all modules and functionalities of the Neos backend. - parentRoles: ['Neos.Neos:Editor'] privileges: -