Skip to content

Commit

Permalink
BUGFIX: Allow to specify WorkspaceRoleAssignments when creating a n…
Browse files Browse the repository at this point in the history
…ew shared workspace

... otherwise authentication fails and the workspace roles cannot be assigned because management is not granted (yet) - only admins would be able to do that.
  • Loading branch information
mhsdesign committed Dec 9, 2024
1 parent 06348d5 commit 6d0a149
Show file tree
Hide file tree
Showing 7 changed files with 55 additions and 23 deletions.
2 changes: 2 additions & 0 deletions Neos.Neos/Classes/Command/WorkspaceCommandController.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
use Neos\Neos\Domain\Model\WorkspaceDescription;
use Neos\Neos\Domain\Model\WorkspaceRole;
use Neos\Neos\Domain\Model\WorkspaceRoleAssignment;
use Neos\Neos\Domain\Model\WorkspaceRoleAssignments;
use Neos\Neos\Domain\Model\WorkspaceRoleSubject;
use Neos\Neos\Domain\Model\WorkspaceRoleSubjectType;
use Neos\Neos\Domain\Model\WorkspaceTitle;
Expand Down Expand Up @@ -205,6 +206,7 @@ public function createSharedCommand(string $workspace, string $baseWorkspace = '
WorkspaceTitle::fromString($title ?? $workspaceName->value),
WorkspaceDescription::fromString($description ?? ''),
WorkspaceName::fromString($baseWorkspace),
WorkspaceRoleAssignments::createEmpty()
);
$this->outputLine('<success>Created shared workspace "%s"</success>', [$workspaceName->value]);
}
Expand Down
10 changes: 10 additions & 0 deletions Neos.Neos/Classes/Domain/Model/WorkspaceRoleAssignments.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ private function __construct(WorkspaceRoleAssignment ...$assignments)
$this->assignments = $assignments;
}

public static function createEmpty(): self
{
return new self();
}

public static function create(WorkspaceRoleAssignment ...$assignments): self
{
return new self(...$assignments);
}

/**
* @param array<WorkspaceRoleAssignment> $assignments
*/
Expand Down
7 changes: 6 additions & 1 deletion Neos.Neos/Classes/Domain/Service/WorkspaceService.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,15 @@ public function createPersonalWorkspace(ContentRepositoryId $contentRepositoryId

/**
* Create a new, potentially shared, workspace
*
* NOTE: By default - if no role assignments are specified - only administrators can manage workspaces without role assignments.
*/
public function createSharedWorkspace(ContentRepositoryId $contentRepositoryId, WorkspaceName $workspaceName, WorkspaceTitle $title, WorkspaceDescription $description, WorkspaceName $baseWorkspaceName): void
public function createSharedWorkspace(ContentRepositoryId $contentRepositoryId, WorkspaceName $workspaceName, WorkspaceTitle $title, WorkspaceDescription $description, WorkspaceName $baseWorkspaceName, WorkspaceRoleAssignments $workspaceRoleAssignments): void
{
$this->createWorkspace($contentRepositoryId, $workspaceName, $title, $description, $baseWorkspaceName, null, WorkspaceClassification::SHARED);
foreach ($workspaceRoleAssignments as $assignment) {
$this->metadataAndRoleRepository->assignWorkspaceRole($contentRepositoryId, $workspaceName, $assignment);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@ public function getWorkspacePermissions(ContentRepositoryId $contentRepositoryId
if ($userId !== null) {
$subjects[] = WorkspaceRoleSubject::createForUser($userId);
}
/**
* We hardcode the check against administrators to always grant manage permissions. This is done to allow administrators to fix permissions of all workspaces.
* We don't allow all rights like read and write. Admins should be able to grant themselves permissions to write to other personal workspaces, but they should not have this permission automagically.
*/
$userIsAdministrator = in_array(self::ROLE_NEOS_ADMINISTRATOR, $roleIdentifiers, true);
$userWorkspaceRole = $this->metadataAndRoleRepository->getMostPrivilegedWorkspaceRoleForSubjects($contentRepositoryId, $workspaceName, WorkspaceRoleSubjects::fromArray($subjects));
if ($userWorkspaceRole === null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
use Neos\Neos\Domain\Model\WorkspaceDescription;
use Neos\Neos\Domain\Model\WorkspaceRole;
use Neos\Neos\Domain\Model\WorkspaceRoleAssignment;
use Neos\Neos\Domain\Model\WorkspaceRoleAssignments;
use Neos\Neos\Domain\Model\WorkspaceRoleSubject;
use Neos\Neos\Domain\Model\WorkspaceRoleSubjectType;
use Neos\Neos\Domain\Model\WorkspaceTitle;
use Neos\Neos\Domain\Service\UserService;
use Neos\Neos\Domain\Service\WorkspaceService;
Expand Down Expand Up @@ -112,15 +114,28 @@ public function aPersonalWorkspaceForUserIsCreated(string $username): void

/**
* @When the shared workspace :workspaceName is created with the target workspace :targetWorkspace
* @When the shared workspace :workspaceName is created with the target workspace :targetWorkspace and role assignments:
*/
public function theSharedWorkspaceIsCreatedWithTheTargetWorkspace(string $workspaceName, string $targetWorkspace): void
public function theSharedWorkspaceIsCreatedWithTheTargetWorkspace(string $workspaceName, string $targetWorkspace, ?TableNode $rawRoleAssignments = null): void
{
$workspaceRoleAssignments = [];
foreach ($rawRoleAssignments?->getHash() ?? [] as $row) {
$workspaceRoleAssignments[] = WorkspaceRoleAssignment::create(
WorkspaceRoleSubject::create(
WorkspaceRoleSubjectType::from($row['Type']),
$row['Value']
),
WorkspaceRole::from($row['Role'])
);
}

$this->tryCatchingExceptions(fn () => $this->getObject(WorkspaceService::class)->createSharedWorkspace(
$this->currentContentRepository->id,
WorkspaceName::fromString($workspaceName),
WorkspaceTitle::fromString($workspaceName),
WorkspaceDescription::fromString(''),
WorkspaceName::fromString($targetWorkspace),
WorkspaceRoleAssignments::fromArray($workspaceRoleAssignments)
));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,16 @@ Feature: Workspace permission related features
# neos user with out any editing roles
| simple_user | Neos.Neos:UserManager |

And the shared workspace "shared-workspace" is created with the target workspace "live"
And the role COLLABORATOR is assigned to workspace "shared-workspace" for group "Neos.Neos:AbstractEditor"
When content repository security is enabled
And the shared workspace "shared-workspace" is created with the target workspace "live" and role assignments:
| Role | Type | Value |
| COLLABORATOR | GROUP | Neos.Neos:AbstractEditor |

Given I am authenticated as owner
And the personal workspace "workspace" is created with the target workspace "live" for user "owner"
And the role MANAGER is assigned to workspace "workspace" for user "manager"
And the role COLLABORATOR is assigned to workspace "workspace" for user "collaborator"

When content repository security is enabled

Scenario Outline: Creating a root workspace
Given I am authenticated as <user>
When the command CreateRootWorkspace is executed with payload '{"workspaceName":"new-ws","newContentStreamId":"new-cs"}' and exceptions are caught
Expand Down
29 changes: 12 additions & 17 deletions Neos.Workspace.Ui/Classes/Controller/WorkspaceController.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
use Neos\Neos\Domain\Model\WorkspaceDescription;
use Neos\Neos\Domain\Model\WorkspaceRole;
use Neos\Neos\Domain\Model\WorkspaceRoleAssignment;
use Neos\Neos\Domain\Model\WorkspaceRoleAssignments;
use Neos\Neos\Domain\Model\WorkspaceTitle;
use Neos\Neos\Domain\Repository\SiteRepository;
use Neos\Neos\Domain\Service\NodeTypeNameFactory;
Expand Down Expand Up @@ -222,6 +223,16 @@ public function createAction(
$title,
$description,
$baseWorkspace,
WorkspaceRoleAssignments::create(
WorkspaceRoleAssignment::createForUser(
$currentUser->getId(),
WorkspaceRole::MANAGER,
),
WorkspaceRoleAssignment::createForGroup(
'Neos.Neos:AbstractEditor',
WorkspaceRole::COLLABORATOR,
)
)
);
} catch (WorkspaceAlreadyExists $exception) {
$this->addFlashMessage(
Expand All @@ -231,22 +242,6 @@ public function createAction(
);
$this->redirect('new');
}
$this->workspaceService->assignWorkspaceRole(
$contentRepositoryId,
$workspaceName,
WorkspaceRoleAssignment::createForUser(
$currentUser->getId(),
WorkspaceRole::MANAGER,
)
);
$this->workspaceService->assignWorkspaceRole(
$contentRepositoryId,
$workspaceName,
WorkspaceRoleAssignment::createForGroup(
'Neos.Neos:AbstractEditor',
WorkspaceRole::COLLABORATOR,
)
);
$this->addFlashMessage($this->getModuleLabel('workspaces.workspaceHasBeenCreated', [$title->value]));
$this->redirect('index');
}
Expand Down Expand Up @@ -1029,7 +1024,7 @@ protected function prepareBaseWorkspaceOptions(
continue;
}
$permissions = $this->contentRepositoryAuthorizationService->getWorkspacePermissions($contentRepository->id, $workspace->workspaceName, $this->securityContext->getRoles(), $currentUser?->getId());
if (!$permissions->manage) {
if (!$permissions->read) {
continue;
}
$baseWorkspaceOptions[$workspace->workspaceName->value] = $workspaceMetadata->title->value;
Expand Down

0 comments on commit 6d0a149

Please sign in to comment.