Skip to content

Commit

Permalink
Merge pull request #5306 from mficzel/bugfix/pruneRoleAssignmentsAndW…
Browse files Browse the repository at this point in the history
…orkspaceMetadataWithCr

BUGFIX: Ensure workspace roles and metadata are pruned with the CR.
  • Loading branch information
skurfuerst authored Oct 21, 2024
2 parents e984fe3 + 4f2ac23 commit bb3119a
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
use Neos\EventStore\Model\Event\SequenceNumber;
use Neos\EventStore\Model\EventStore\StatusType;
use Neos\Flow\Cli\CommandController;
use Neos\Neos\Domain\Service\WorkspaceService;
use Symfony\Component\Console\Helper\ProgressBar;
use Symfony\Component\Console\Output\ConsoleOutput;
use Symfony\Component\Console\Output\Output;
Expand Down Expand Up @@ -204,44 +205,4 @@ public function projectionReplayAllCommand(string $contentRepository = 'default'
$this->outputLine('<success>Done.</success>');
}
}

/**
* This will completely prune the data of the specified content repository.
*
* @param string $contentRepository Name of the content repository where the data should be pruned from.
* @param bool $force Prune the cr without confirmation. This cannot be reverted!
* @return void
*/
public function pruneCommand(string $contentRepository = 'default', bool $force = false): void
{
if (!$force && !$this->output->askConfirmation(sprintf('> This will prune your content repository "%s". Are you sure to proceed? (y/n) ', $contentRepository), false)) {
$this->outputLine('<comment>Abort.</comment>');
return;
}

$contentRepositoryId = ContentRepositoryId::fromString($contentRepository);

$contentStreamPruner = $this->contentRepositoryRegistry->buildService(
$contentRepositoryId,
new ContentStreamPrunerFactory()
);

$workspaceMaintenanceService = $this->contentRepositoryRegistry->buildService(
$contentRepositoryId,
new WorkspaceMaintenanceServiceFactory()
);

$projectionService = $this->contentRepositoryRegistry->buildService(
$contentRepositoryId,
$this->projectionServiceFactory
);

// reset the events table
$contentStreamPruner->pruneAll();
$workspaceMaintenanceService->pruneAll();
// reset the projections state
$projectionService->resetAllProjections();

$this->outputLine('<success>Done.</success>');
}
}
48 changes: 48 additions & 0 deletions Neos.Neos/Classes/Command/CrCommandController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use League\Flysystem\Filesystem;
use League\Flysystem\Local\LocalFilesystemAdapter;
use Neos\ContentRepository\Core\Projection\CatchUpOptions;
use Neos\ContentRepository\Core\Service\ContentStreamPrunerFactory;
use Neos\ContentRepository\Core\Service\WorkspaceMaintenanceServiceFactory;
use Neos\ContentRepository\Core\SharedModel\ContentRepository\ContentRepositoryId;
use Neos\ContentRepository\Core\SharedModel\Workspace\ContentStreamId;
use Neos\ContentRepository\Core\SharedModel\Workspace\WorkspaceName;
Expand Down Expand Up @@ -39,6 +41,7 @@ public function __construct(
private readonly ProjectionReplayServiceFactory $projectionReplayServiceFactory,
private readonly AssetUsageService $assetUsageService,
private readonly WorkspaceService $workspaceService,
private readonly ProjectionReplayServiceFactory $projectionServiceFactory,
) {
parent::__construct();
}
Expand Down Expand Up @@ -125,4 +128,49 @@ public function importCommand(string $path, string $contentRepository = 'default

$this->outputLine('<success>Done</success>');
}

/**
* This will completely prune the data of the specified content repository.
*
* @param string $contentRepository Name of the content repository where the data should be pruned from.
* @param bool $force Prune the cr without confirmation. This cannot be reverted!
* @return void
*/
public function pruneCommand(string $contentRepository = 'default', bool $force = false): void
{
if (!$force && !$this->output->askConfirmation(sprintf('> This will prune your content repository "%s". Are you sure to proceed? (y/n) ', $contentRepository), false)) {
$this->outputLine('<comment>Abort.</comment>');
return;
}

$contentRepositoryId = ContentRepositoryId::fromString($contentRepository);

$contentStreamPruner = $this->contentRepositoryRegistry->buildService(
$contentRepositoryId,
new ContentStreamPrunerFactory()
);

$workspaceMaintenanceService = $this->contentRepositoryRegistry->buildService(
$contentRepositoryId,
new WorkspaceMaintenanceServiceFactory()
);

$projectionService = $this->contentRepositoryRegistry->buildService(
$contentRepositoryId,
$this->projectionServiceFactory
);

// remove the workspace metadata and roles for this cr
$this->workspaceService->pruneRoleAsssignments($contentRepositoryId);
$this->workspaceService->pruneWorkspaceMetadata($contentRepositoryId);

// reset the events table
$contentStreamPruner->pruneAll();
$workspaceMaintenanceService->pruneAll();

// reset the projections state
$projectionService->resetAllProjections();

$this->outputLine('<success>Done.</success>');
}
}
22 changes: 22 additions & 0 deletions Neos.Neos/Classes/Domain/Service/WorkspaceService.php
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,28 @@ private function updateWorkspaceMetadata(ContentRepositoryId $contentRepositoryI
}
}

public function pruneWorkspaceMetadata(ContentRepositoryId $contentRepositoryId): void
{
try {
$this->dbal->delete(self::TABLE_NAME_WORKSPACE_METADATA, [
'content_repository_id' => $contentRepositoryId->value,
]);
} catch (DbalException $e) {
throw new \RuntimeException(sprintf('Failed to prune workspace metadata Content Repository "%s": %s', $contentRepositoryId->value, $e->getMessage()), 1729512100, $e);
}
}

public function pruneRoleAsssignments(ContentRepositoryId $contentRepositoryId): void
{
try {
$this->dbal->delete(self::TABLE_NAME_WORKSPACE_ROLE, [
'content_repository_id' => $contentRepositoryId->value,
]);
} catch (DbalException $e) {
throw new \RuntimeException(sprintf('Failed to prune workspace roles for Content Repository "%s": %s', $contentRepositoryId->value, $e->getMessage()), 1729512142, $e);
}
}

private function createWorkspace(ContentRepositoryId $contentRepositoryId, WorkspaceName $workspaceName, WorkspaceTitle $title, WorkspaceDescription $description, WorkspaceName $baseWorkspaceName, UserId|null $ownerId, WorkspaceClassification $classification): void
{
$contentRepository = $this->contentRepositoryRegistry->get($contentRepositoryId);
Expand Down

0 comments on commit bb3119a

Please sign in to comment.