From 0e15553fe8ad16f80883a4ab66c3aef61ab9e26a Mon Sep 17 00:00:00 2001 From: buchholz Date: Fri, 12 Jul 2024 19:00:25 +0200 Subject: [PATCH 1/6] FIX: show workspace owner/title in media usage tab - configurable privilege roles Issue: https://github.com/neos/neos-development-collection/issues/5181 --- .../Classes/Controller/UsageController.php | 29 ++++++++++++++++++- .../Configuration/Settings.yaml | 4 +++ .../Private/Templates/Usage/RelatedNodes.html | 3 ++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Neos.Media.Browser/Classes/Controller/UsageController.php b/Neos.Media.Browser/Classes/Controller/UsageController.php index 76703174097..b07e018f256 100644 --- a/Neos.Media.Browser/Classes/Controller/UsageController.php +++ b/Neos.Media.Browser/Classes/Controller/UsageController.php @@ -20,6 +20,7 @@ use Neos\Eel\FlowQuery\FlowQuery; use Neos\Flow\Annotations as Flow; use Neos\Flow\Mvc\Controller\ActionController; +use Neos\Flow\Security\Context; use Neos\Media\Domain\Model\AssetInterface; use Neos\Media\Domain\Service\AssetService; use Neos\Neos\Controller\CreateContentContextTrait; @@ -80,6 +81,18 @@ class UsageController extends ActionController */ protected $domainUserService; + /** + * @Flow\Inject + * @var Context + */ + protected $securityContext; + + /** + * @Flow\InjectConfiguration(package="Neos.Media.Browser", path="features.showWorkspaceOwnerOrName") + * @var array + */ + protected $showWorkspaceOwnerOrNameConfiguration; + /** * Get Related Nodes for an asset * @@ -89,6 +102,19 @@ class UsageController extends ActionController public function relatedNodesAction(AssetInterface $asset) { $userWorkspace = $this->userService->getPersonalWorkspace(); + $currentAccount = $this->securityContext->getAccount(); + + $isPrivilegedRole = false; + if ($currentAccount != null && $this->showWorkspaceOwnerOrNameConfiguration['enable']) { + $roles = array_keys($currentAccount->getRoles()); + + foreach ($this->showWorkspaceOwnerOrNameConfiguration['privilegedRoles'] as $role) { + if (in_array($role, $roles)) { + $isPrivilegedRole = true; + break; + } + } + } $usageReferences = $this->assetService->getUsageReferences($asset); $relatedNodes = []; @@ -165,7 +191,8 @@ public function relatedNodesAction(AssetInterface $asset) 'inaccessibleRelations' => $inaccessibleRelations, 'relatedNodes' => $relatedNodes, 'contentDimensions' => $this->contentDimensionPresetSource->getAllPresets(), - 'userWorkspace' => $userWorkspace + 'userWorkspace' => $userWorkspace, + 'isPrivilegedRole' => $isPrivilegedRole, ]); } diff --git a/Neos.Media.Browser/Configuration/Settings.yaml b/Neos.Media.Browser/Configuration/Settings.yaml index ec7c29899eb..d7f0e57a0d8 100644 --- a/Neos.Media.Browser/Configuration/Settings.yaml +++ b/Neos.Media.Browser/Configuration/Settings.yaml @@ -27,6 +27,10 @@ Neos: # By default, enable the option to create redirects for replaced asset resources createAssetRedirectsOption: enable: true + # By default, disable showing the workspace owner/title in media browser usage tab + showWorkspaceOwnerOrName: + enable: false + privilegedRoles: ['Neos.Neos:Administrator'] Flow: security: diff --git a/Neos.Media.Browser/Resources/Private/Templates/Usage/RelatedNodes.html b/Neos.Media.Browser/Resources/Private/Templates/Usage/RelatedNodes.html index 8dde5d9cb3a..c41ebfe29b2 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.workspace.title}) {neos:backend.translate(id: 'workspaces.privateWorkspace', source: 'Modules', package: 'Neos.Neos')} + ({inaccessibleRelation.workspace.owner.name.fullName}) {neos:backend.translate(id: 'workspaces.internalWorkspace', source: 'Modules', package: 'Neos.Neos')} + ({inaccessibleRelation.workspace.title}) --- From 3f5f41ce5cf33c4447719cd5596d4b51dc43f36f Mon Sep 17 00:00:00 2001 From: buchholz Date: Thu, 25 Jul 2024 15:27:24 +0200 Subject: [PATCH 2/6] BUGFIX: introduce a new role for displaying the workspace owner - new role `Neos.Media.Browser:WorkspaceName` - add new role to `Neos.Neos:Administrator` as parent role - enable showing the workspace owner by default - adjust UsageController.php to check if current user role matches the new role Issue: https://github.com/neos/neos-development-collection/issues/5181 --- .../Classes/Controller/UsageController.php | 24 +++++++++---------- Neos.Media.Browser/Configuration/Policy.yaml | 3 +++ .../Configuration/Settings.yaml | 3 +-- Neos.Neos/Configuration/Policy.yaml | 3 +-- 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/Neos.Media.Browser/Classes/Controller/UsageController.php b/Neos.Media.Browser/Classes/Controller/UsageController.php index b07e018f256..1a0eb2c04ab 100644 --- a/Neos.Media.Browser/Classes/Controller/UsageController.php +++ b/Neos.Media.Browser/Classes/Controller/UsageController.php @@ -21,6 +21,7 @@ use Neos\Flow\Annotations as Flow; use Neos\Flow\Mvc\Controller\ActionController; use Neos\Flow\Security\Context; +use Neos\Flow\Security\Policy\PolicyService; use Neos\Media\Domain\Model\AssetInterface; use Neos\Media\Domain\Service\AssetService; use Neos\Neos\Controller\CreateContentContextTrait; @@ -87,6 +88,12 @@ class UsageController extends ActionController */ protected $securityContext; + /** + * @Flow\Inject + * @var PolicyService + */ + protected $policyService; + /** * @Flow\InjectConfiguration(package="Neos.Media.Browser", path="features.showWorkspaceOwnerOrName") * @var array @@ -106,14 +113,7 @@ public function relatedNodesAction(AssetInterface $asset) $isPrivilegedRole = false; if ($currentAccount != null && $this->showWorkspaceOwnerOrNameConfiguration['enable']) { - $roles = array_keys($currentAccount->getRoles()); - - foreach ($this->showWorkspaceOwnerOrNameConfiguration['privilegedRoles'] as $role) { - if (in_array($role, $roles)) { - $isPrivilegedRole = true; - break; - } - } + $isPrivilegedRole = $this->securityContext->hasRole('Neos.Media.Browser:WorkspaceName'); } $usageReferences = $this->assetService->getUsageReferences($asset); @@ -204,10 +204,10 @@ private function getNodeFrom(AssetUsageInNodeProperties $assetUsage) { $context = $this->_contextFactory->create( [ - 'workspaceName' => $assetUsage->getWorkspaceName(), - 'dimensions' => $assetUsage->getDimensionValues(), - 'invisibleContentShown' => true, - 'removedContentShown' => true] + 'workspaceName' => $assetUsage->getWorkspaceName(), + 'dimensions' => $assetUsage->getDimensionValues(), + 'invisibleContentShown' => true, + 'removedContentShown' => true] ); return $context->getNodeByIdentifier($assetUsage->getNodeIdentifier()); } diff --git a/Neos.Media.Browser/Configuration/Policy.yaml b/Neos.Media.Browser/Configuration/Policy.yaml index a237114296c..984b55cae7a 100644 --- a/Neos.Media.Browser/Configuration/Policy.yaml +++ b/Neos.Media.Browser/Configuration/Policy.yaml @@ -29,6 +29,9 @@ privilegeTargets: matcher: 'method(Neos\Media\Browser\Controller\(Asset|Image)Controller->(replaceAssetResource|updateAssetResource)Action())' roles: + 'Neos.Media.Browser:WorkspaceName': + abstract: true + 'Neos.Neos:AbstractEditor': privileges: - diff --git a/Neos.Media.Browser/Configuration/Settings.yaml b/Neos.Media.Browser/Configuration/Settings.yaml index d7f0e57a0d8..6167bfb89fa 100644 --- a/Neos.Media.Browser/Configuration/Settings.yaml +++ b/Neos.Media.Browser/Configuration/Settings.yaml @@ -29,8 +29,7 @@ Neos: enable: true # By default, disable showing the workspace owner/title in media browser usage tab showWorkspaceOwnerOrName: - enable: false - privilegedRoles: ['Neos.Neos:Administrator'] + enable: true Flow: security: diff --git a/Neos.Neos/Configuration/Policy.yaml b/Neos.Neos/Configuration/Policy.yaml index 004c42eee77..b067f7a2365 100644 --- a/Neos.Neos/Configuration/Policy.yaml +++ b/Neos.Neos/Configuration/Policy.yaml @@ -325,8 +325,7 @@ roles: 'Neos.Neos:Administrator': label: Neos Administrator description: Grants access to all modules and functionalities of the Neos backend. - - parentRoles: ['Neos.Neos:Editor'] + parentRoles: ['Neos.Neos:Editor', 'Neos.Media.Browser:WorkspaceName'] privileges: - privilegeTarget: 'Neos.Neos:Backend.Module.Administration' From 421f7a87bea5d3ee2b52ace1ea61c3f6f1041167 Mon Sep 17 00:00:00 2001 From: buchholz Date: Fri, 26 Jul 2024 08:16:46 +0200 Subject: [PATCH 3/6] BUGFIX: remove unused variable in controller - remove unused variable `$policyService` and import in UsageController.php and fix formatting - correct commentary in Settings.yaml Issue: https://github.com/neos/neos-development-collection/issues/5181 --- .../Classes/Controller/UsageController.php | 20 ++++++------------- .../Configuration/Settings.yaml | 2 +- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/Neos.Media.Browser/Classes/Controller/UsageController.php b/Neos.Media.Browser/Classes/Controller/UsageController.php index 1a0eb2c04ab..d1b24b001a1 100644 --- a/Neos.Media.Browser/Classes/Controller/UsageController.php +++ b/Neos.Media.Browser/Classes/Controller/UsageController.php @@ -21,7 +21,6 @@ use Neos\Flow\Annotations as Flow; use Neos\Flow\Mvc\Controller\ActionController; use Neos\Flow\Security\Context; -use Neos\Flow\Security\Policy\PolicyService; use Neos\Media\Domain\Model\AssetInterface; use Neos\Media\Domain\Service\AssetService; use Neos\Neos\Controller\CreateContentContextTrait; @@ -88,12 +87,6 @@ class UsageController extends ActionController */ protected $securityContext; - /** - * @Flow\Inject - * @var PolicyService - */ - protected $policyService; - /** * @Flow\InjectConfiguration(package="Neos.Media.Browser", path="features.showWorkspaceOwnerOrName") * @var array @@ -202,13 +195,12 @@ public function relatedNodesAction(AssetInterface $asset) */ private function getNodeFrom(AssetUsageInNodeProperties $assetUsage) { - $context = $this->_contextFactory->create( - [ - 'workspaceName' => $assetUsage->getWorkspaceName(), - 'dimensions' => $assetUsage->getDimensionValues(), - 'invisibleContentShown' => true, - 'removedContentShown' => true] - ); + $context = $this->_contextFactory->create([ + 'workspaceName' => $assetUsage->getWorkspaceName(), + 'dimensions' => $assetUsage->getDimensionValues(), + 'invisibleContentShown' => true, + 'removedContentShown' => true + ]); return $context->getNodeByIdentifier($assetUsage->getNodeIdentifier()); } } diff --git a/Neos.Media.Browser/Configuration/Settings.yaml b/Neos.Media.Browser/Configuration/Settings.yaml index 6167bfb89fa..99b04014ff9 100644 --- a/Neos.Media.Browser/Configuration/Settings.yaml +++ b/Neos.Media.Browser/Configuration/Settings.yaml @@ -27,7 +27,7 @@ Neos: # By default, enable the option to create redirects for replaced asset resources createAssetRedirectsOption: enable: true - # By default, disable showing the workspace owner/title in media browser usage tab + # By default, enable showing the workspace owner/title in media browser usage tab showWorkspaceOwnerOrName: enable: true From 35b3be1ebe93a88073138f146a52cd87a2ca2684 Mon Sep 17 00:00:00 2001 From: buchholz Date: Fri, 26 Jul 2024 11:49:34 +0200 Subject: [PATCH 4/6] BUGFIX: introduce new privilege target `Neos.Media.Browser:WorkspaceName` instead of the role - introduce new privilege target `Neos.Media.Browser:WorkspaceName`, grant privilege to `Neos.Neos:Administrator` and remove obsolet abstract role `Neos.Media.Browser:WorkspaceName` - remove unnecessary parent role from `Neos.Neos:Administrator` - remove config in Settings.yaml - adjust UsageController.php to work with new privilege target Issue: https://github.com/neos/neos-development-collection/issues/5181 --- .../Classes/Controller/UsageController.php | 11 ++++++----- Neos.Media.Browser/Configuration/Policy.yaml | 10 +++++++--- Neos.Media.Browser/Configuration/Settings.yaml | 3 --- Neos.Neos/Configuration/Policy.yaml | 2 +- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/Neos.Media.Browser/Classes/Controller/UsageController.php b/Neos.Media.Browser/Classes/Controller/UsageController.php index d1b24b001a1..d70b8484cbc 100644 --- a/Neos.Media.Browser/Classes/Controller/UsageController.php +++ b/Neos.Media.Browser/Classes/Controller/UsageController.php @@ -20,6 +20,7 @@ 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; @@ -88,10 +89,10 @@ class UsageController extends ActionController protected $securityContext; /** - * @Flow\InjectConfiguration(package="Neos.Media.Browser", path="features.showWorkspaceOwnerOrName") - * @var array + * @Flow\Inject + * @var PrivilegeManagerInterface */ - protected $showWorkspaceOwnerOrNameConfiguration; + protected $privilegeManager; /** * Get Related Nodes for an asset @@ -105,8 +106,8 @@ public function relatedNodesAction(AssetInterface $asset) $currentAccount = $this->securityContext->getAccount(); $isPrivilegedRole = false; - if ($currentAccount != null && $this->showWorkspaceOwnerOrNameConfiguration['enable']) { - $isPrivilegedRole = $this->securityContext->hasRole('Neos.Media.Browser:WorkspaceName'); + if ($currentAccount != null) { + $isPrivilegedRole = $this->privilegeManager->isPrivilegeTargetGranted('Neos.Media.Browser:WorkspaceName'); } $usageReferences = $this->assetService->getUsageReferences($asset); diff --git a/Neos.Media.Browser/Configuration/Policy.yaml b/Neos.Media.Browser/Configuration/Policy.yaml index 984b55cae7a..8f597c69e27 100644 --- a/Neos.Media.Browser/Configuration/Policy.yaml +++ b/Neos.Media.Browser/Configuration/Policy.yaml @@ -28,10 +28,11 @@ privilegeTargets: label: Allowed to replace asset resources matcher: 'method(Neos\Media\Browser\Controller\(Asset|Image)Controller->(replaceAssetResource|updateAssetResource)Action())' -roles: - 'Neos.Media.Browser:WorkspaceName': - abstract: true + 'Neos.Media.Browser:WorkspaceName': + label: Allowed to see workspace owner + matcher: 'method(Neos\Media\Browser\Controller\UsageController->relatedNodesAction())' +roles: 'Neos.Neos:AbstractEditor': privileges: - @@ -58,6 +59,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/Configuration/Settings.yaml b/Neos.Media.Browser/Configuration/Settings.yaml index 99b04014ff9..ec7c29899eb 100644 --- a/Neos.Media.Browser/Configuration/Settings.yaml +++ b/Neos.Media.Browser/Configuration/Settings.yaml @@ -27,9 +27,6 @@ Neos: # By default, enable the option to create redirects for replaced asset resources createAssetRedirectsOption: enable: true - # By default, enable showing the workspace owner/title in media browser usage tab - showWorkspaceOwnerOrName: - enable: true Flow: security: diff --git a/Neos.Neos/Configuration/Policy.yaml b/Neos.Neos/Configuration/Policy.yaml index b067f7a2365..16558e14c01 100644 --- a/Neos.Neos/Configuration/Policy.yaml +++ b/Neos.Neos/Configuration/Policy.yaml @@ -325,7 +325,7 @@ roles: 'Neos.Neos:Administrator': label: Neos Administrator description: Grants access to all modules and functionalities of the Neos backend. - parentRoles: ['Neos.Neos:Editor', 'Neos.Media.Browser:WorkspaceName'] + parentRoles: ['Neos.Neos:Editor'] privileges: - privilegeTarget: 'Neos.Neos:Backend.Module.Administration' From 1d034a8ad0b74dd63a903f39576e79ab087ebb50 Mon Sep 17 00:00:00 2001 From: buchholz Date: Mon, 29 Jul 2024 10:33:21 +0200 Subject: [PATCH 5/6] BUGFIX: new method to return label containing the workspace title/owner - UsageController.php: introduce new method to return `label` for workspace title based on privilege target and workspace type - RelatedNodes.html: use new `label` for rendering Issue: https://github.com/neos/neos-development-collection/issues/5181 --- .../Classes/Controller/UsageController.php | 24 +++++++++++++------ .../Private/Templates/Usage/RelatedNodes.html | 6 ++--- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/Neos.Media.Browser/Classes/Controller/UsageController.php b/Neos.Media.Browser/Classes/Controller/UsageController.php index d70b8484cbc..cbc866087c8 100644 --- a/Neos.Media.Browser/Classes/Controller/UsageController.php +++ b/Neos.Media.Browser/Classes/Controller/UsageController.php @@ -103,12 +103,6 @@ class UsageController extends ActionController public function relatedNodesAction(AssetInterface $asset) { $userWorkspace = $this->userService->getPersonalWorkspace(); - $currentAccount = $this->securityContext->getAccount(); - - $isPrivilegedRole = false; - if ($currentAccount != null) { - $isPrivilegedRole = $this->privilegeManager->isPrivilegeTargetGranted('Neos.Media.Browser:WorkspaceName'); - } $usageReferences = $this->assetService->getUsageReferences($asset); $relatedNodes = []; @@ -136,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; @@ -186,7 +181,6 @@ public function relatedNodesAction(AssetInterface $asset) 'relatedNodes' => $relatedNodes, 'contentDimensions' => $this->contentDimensionPresetSource->getAllPresets(), 'userWorkspace' => $userWorkspace, - 'isPrivilegedRole' => $isPrivilegedRole, ]); } @@ -204,4 +198,20 @@ private function getNodeFrom(AssetUsageInNodeProperties $assetUsage) ]); 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/Resources/Private/Templates/Usage/RelatedNodes.html b/Neos.Media.Browser/Resources/Private/Templates/Usage/RelatedNodes.html index c41ebfe29b2..5d9f6345885 100644 --- a/Neos.Media.Browser/Resources/Private/Templates/Usage/RelatedNodes.html +++ b/Neos.Media.Browser/Resources/Private/Templates/Usage/RelatedNodes.html @@ -39,7 +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.workspace.title}) + {inaccessibleRelation.label} {neos:backend.translate(id: 'workspaces.privateWorkspace', source: 'Modules', package: 'Neos.Neos')} - ({inaccessibleRelation.workspace.owner.name.fullName}) + {inaccessibleRelation.label} {neos:backend.translate(id: 'workspaces.internalWorkspace', source: 'Modules', package: 'Neos.Neos')} - ({inaccessibleRelation.workspace.title}) + {inaccessibleRelation.label} --- From bbeb8df60d67792ea60b1d90684d856c14d40c3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Kurf=C3=BCrst?= Date: Wed, 23 Oct 2024 11:12:19 +0200 Subject: [PATCH 6/6] add minor comment when reviewing --- Neos.Media.Browser/Configuration/Policy.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Neos.Media.Browser/Configuration/Policy.yaml b/Neos.Media.Browser/Configuration/Policy.yaml index 8f597c69e27..19058da9497 100644 --- a/Neos.Media.Browser/Configuration/Policy.yaml +++ b/Neos.Media.Browser/Configuration/Policy.yaml @@ -28,6 +28,8 @@ 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())'