diff --git a/Neos.Neos/Classes/Domain/Model/WorkspacePermissions.php b/Neos.Neos/Classes/Domain/Model/WorkspacePermissions.php index faf543259cf..05dd0945556 100644 --- a/Neos.Neos/Classes/Domain/Model/WorkspacePermissions.php +++ b/Neos.Neos/Classes/Domain/Model/WorkspacePermissions.php @@ -47,4 +47,9 @@ public static function all(): self { return new self(true, true, true); } + + public static function none(): self + { + return new self(false, false, false); + } } diff --git a/Neos.Neos/Classes/Domain/Service/WorkspaceService.php b/Neos.Neos/Classes/Domain/Service/WorkspaceService.php index 7e82fe9cac4..187fc97a464 100644 --- a/Neos.Neos/Classes/Domain/Service/WorkspaceService.php +++ b/Neos.Neos/Classes/Domain/Service/WorkspaceService.php @@ -289,19 +289,30 @@ public function getWorkspacePermissionsForUser(ContentRepositoryId $contentRepos } catch (NoSuchRoleException $e) { throw new \RuntimeException(sprintf('Failed to determine roles for user "%s", check your package dependencies: %s', $user->getId()->value, $e->getMessage()), 1727084881, $e); } + + $userIsAdministrator = in_array('Neos.Neos:Administrator', $userRoles, true); + + if ($userIsAdministrator) { + return WorkspacePermissions::all(); + } + $workspaceMetadata = $this->loadWorkspaceMetadata($contentRepositoryId, $workspaceName); - if ($workspaceMetadata !== null && $workspaceMetadata->ownerUserId !== null && $workspaceMetadata->ownerUserId->equals($user->getId())) { + $userIsOwner = $workspaceMetadata !== null && $workspaceMetadata->ownerUserId !== null && $workspaceMetadata->ownerUserId->equals($user->getId()); + + if ($userIsOwner) { return WorkspacePermissions::all(); } + $userWorkspaceRole = $this->loadWorkspaceRoleOfUser($contentRepositoryId, $workspaceName, $user->getId(), $userRoles); - $userIsAdministrator = in_array('Neos.Neos:Administrator', $userRoles, true); + if ($userWorkspaceRole === null) { - return WorkspacePermissions::create(false, false, $userIsAdministrator); + return WorkspacePermissions::none(); } + return WorkspacePermissions::create( read: $userWorkspaceRole->isAtLeast(WorkspaceRole::COLLABORATOR), write: $userWorkspaceRole->isAtLeast(WorkspaceRole::COLLABORATOR), - manage: $userIsAdministrator || $userWorkspaceRole->isAtLeast(WorkspaceRole::MANAGER), + manage: $userWorkspaceRole->isAtLeast(WorkspaceRole::MANAGER), ); } diff --git a/Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php b/Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php index 7ad33b4a37e..fb539a0191f 100644 --- a/Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php +++ b/Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php @@ -58,6 +58,7 @@ use Neos\Neos\Domain\Model\WorkspaceDescription; use Neos\Neos\Domain\Model\WorkspaceRole; use Neos\Neos\Domain\Model\WorkspaceRoleAssignment; +use Neos\Neos\Domain\Model\WorkspaceRoleSubjectType; use Neos\Neos\Domain\Model\WorkspaceTitle; use Neos\Neos\Domain\NodeLabel\NodeLabelGeneratorInterface; use Neos\Neos\Domain\Repository\SiteRepository; @@ -281,6 +282,7 @@ public function editAction(WorkspaceName $workspaceName): void workspaceTitle: $workspaceMetadata->title, workspaceDescription: $workspaceMetadata->description, workspaceHasChanges: $this->computePendingChanges($workspace, $contentRepository)->total > 0, + baseWorkspaceName: $workspace->baseWorkspaceName, baseWorkspaceOptions: $this->prepareBaseWorkspaceOptions($contentRepository, $workspaceName), ); @@ -310,6 +312,12 @@ public function updateAction( } $workspace = $contentRepository->findWorkspaceByName($workspaceName); + + $userCanManageWorkspace = $this->workspaceService->getWorkspacePermissionsForUser($contentRepositoryId, $workspaceName, $this->userService->getCurrentUser())->manage; + if (!$userCanManageWorkspace) { + $this->throwStatus(403); + } + if ($workspace === null) { $this->addFlashMessage( $this->getModuleLabel('workspaces.workspaceDoesNotExist'), @@ -1129,34 +1137,11 @@ public function getModuleLabel(string $id, array $arguments = [], mixed $quantit protected function getUserWorkspace(ContentRepository $contentRepository): Workspace { - /* - $items = []; - $allWorkspaces = $contentRepository->findWorkspaces(); - foreach ($allWorkspaces as $workspace) { - $workspaceMetadata = $this->workspaceService->getWorkspaceMetadata($contentRepositoryId, $workspace->workspaceName); - $permissions = $this->workspaceService->getWorkspacePermissionsForUser($contentRepositoryId, $workspace->workspaceName, $currentUser); - if (!$permissions->read) { - continue; - } - $items[] = new WorkspaceListItem( - name: $workspace->workspaceName->value, - classification: $workspaceMetadata->classification->name, - title: $workspaceMetadata->title->value, - description: $workspaceMetadata->description->value, - baseWorkspaceName: $workspace->baseWorkspaceName?->value, - pendingChanges: $this->computePendingChanges($workspace, $contentRepository), - hasDependantWorkspaces: !$allWorkspaces->getDependantWorkspaces($workspace->workspaceName)->isEmpty(), - permissions: $permissions, - ); - } - */ - $currentUser = $this->userService->getCurrentUser(); if ($currentUser === null) { throw new \RuntimeException('No user is authenticated', 1729505338); } - $userWorkspace = $this->workspaceService->getPersonalWorkspaceForUser($contentRepository->id, $currentUser->getId()); - return $userWorkspace; + return $this->workspaceService->getPersonalWorkspaceForUser($contentRepository->id, $currentUser->getId()); } protected function getWorkspaceListItems( @@ -1172,6 +1157,9 @@ protected function getWorkspaceListItems( $allWorkspaces = $contentRepository->findWorkspaces(); + $userWorkspaceOwner = $this->userService->findUserById($userWorkspaceMetadata->ownerUserId); + + // add user workspace first $workspaceListItems = []; $workspaceListItems[$userWorkspace->workspaceName->value] = new WorkspaceListItem( $userWorkspace->workspaceName->value, @@ -1182,12 +1170,11 @@ protected function getWorkspaceListItems( $userWorkspace->baseWorkspaceName?->value, $this->computePendingChanges($userWorkspace, $contentRepository), !$allWorkspaces->getDependantWorkspaces($userWorkspace->workspaceName)->isEmpty(), - $userWorkspaceMetadata->ownerUserId ? $this->userService->findUserById( - UserId::fromString($userWorkspaceMetadata->ownerUserId->value) - )?->getLabel() : null, + $userWorkspaceOwner?->getLabel(), $userWorkspacesPermissions, ); + // add other, accessible workspaces foreach ($allWorkspaces as $workspace) { $workspaceMetadata = $this->workspaceService->getWorkspaceMetadata($contentRepository->id, $workspace->workspaceName); $workspacesPermissions = $this->workspaceService->getWorkspacePermissionsForUser( @@ -1196,7 +1183,36 @@ protected function getWorkspaceListItems( $this->userService->getCurrentUser() ); - // TODO: check permissions (read?, admin?) + if ($workspacesPermissions->read === false) { + continue; + } + + $workspaceOwner = $workspaceMetadata->ownerUserId + ? $this->userService->findUserById($workspaceMetadata->ownerUserId) + : null; + + $workspaceRoleAssignments = $this->workspaceService->getWorkspaceRoleAssignments($contentRepository->id, $workspace->workspaceName); + + /** + * Managing users of the workspace excluding the owner + * @var array $workspaceManagerUsers + */ + $workspaceManagerUsers = []; + $workspaceManagerGroups = []; + + foreach ($workspaceRoleAssignments as $roleAssignment) { + if ($roleAssignment->role === WorkspaceRole::MANAGER) { + if ($roleAssignment->subjectType == WorkspaceRoleSubjectType::USER) { + $userId = UserId::fromString($roleAssignment->subject->value); + + $workspaceManagerUsers[] = $this->userService + ->findUserById($userId) + ->getLabel(); + } elseif ($roleAssignment->subjectType == WorkspaceRoleSubjectType::GROUP) { + $workspaceManagerGroups[] = $roleAssignment->subject->value; + } + } + } $workspaceListItems[$workspace->workspaceName->value] = new WorkspaceListItem( $workspace->workspaceName->value, @@ -1207,10 +1223,8 @@ protected function getWorkspaceListItems( $workspace->baseWorkspaceName?->value, $this->computePendingChanges($workspace, $contentRepository), !$allWorkspaces->getDependantWorkspaces($workspace->workspaceName)->isEmpty(), - $workspaceMetadata->ownerUserId ? $this->userService->findUserById( - UserId::fromString($workspaceMetadata->ownerUserId->value) - )?->getLabel() : null, - $workspacesPermissions, // todo manage always true???? + $workspaceOwner?->getLabel(), + $workspacesPermissions, ); } return WorkspaceListItems::fromArray($workspaceListItems); diff --git a/Neos.Workspace.Ui/Classes/ViewModel/EditWorkspaceFormData.php b/Neos.Workspace.Ui/Classes/ViewModel/EditWorkspaceFormData.php index de89c3a0536..0553c4f0053 100644 --- a/Neos.Workspace.Ui/Classes/ViewModel/EditWorkspaceFormData.php +++ b/Neos.Workspace.Ui/Classes/ViewModel/EditWorkspaceFormData.php @@ -23,15 +23,16 @@ final readonly class EditWorkspaceFormData { public function __construct( - public WorkspaceName $workspaceName, - public WorkspaceTitle $workspaceTitle, + public WorkspaceName $workspaceName, + public WorkspaceTitle $workspaceTitle, public WorkspaceDescription $workspaceDescription, - public bool $workspaceHasChanges, + public bool $workspaceHasChanges, + public WorkspaceName $baseWorkspaceName, /** * Options for the baseWorkspace selector where the key is the workspace name and the value is the workspace title. * @var array */ - public array $baseWorkspaceOptions, + public array $baseWorkspaceOptions, ) { } diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Components/Modals/Edit.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Components/Modals/Edit.fusion index 3d41ceb6f35..e9c6570dce4 100644 --- a/Neos.Workspace.Ui/Resources/Private/Fusion/Components/Modals/Edit.fusion +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Components/Modals/Edit.fusion @@ -1,5 +1,6 @@ prototype(Neos.Workspace.Ui:Component.Modal.Edit) < prototype(Neos.Fusion:Component) { workspaceHasChanges = false + baseWorkspaceName = '' /// array baseWorkspaceOptions = ${[]} diff --git a/Neos.Workspace.Ui/Resources/Private/Fusion/Components/WorkspaceTable.fusion b/Neos.Workspace.Ui/Resources/Private/Fusion/Components/WorkspaceTable.fusion index 03e9bc37ca2..9de394f459a 100644 --- a/Neos.Workspace.Ui/Resources/Private/Fusion/Components/WorkspaceTable.fusion +++ b/Neos.Workspace.Ui/Resources/Private/Fusion/Components/WorkspaceTable.fusion @@ -23,7 +23,6 @@ prototype(Neos.Workspace.Ui:Component.WorkspaceTable) < prototype(Neos.Fusion:Co {private.i18n.id('workspaces.workspace.description')} - {private.i18n.id('workspaces.workspace.owner')}