Today we released yet another Neos 9 Beta.
This is partially still the aftermath of the Neos sprint and also what we were able to accomplish in the last week
Thanks to all who contributed <3.
Upgrade instructions from Beta 15
previous beta → Neos 9 Beta-15 Release
In your composer.json you should require 9.0.0-beta16
for all Neos packages from the development distribution and for the NeosUi as well as Flow:
"neos/flow": "9.0.0-beta16",
"neos/neos": "9.0.0-beta16",
"neos/neos-ui": "9.0.0-beta16"
The database can be migrated the following way:
A setup to apply the latest schema adjustments:
./flow doctrine:migrate
./flow cr:setup
Additionally, PRs marked with ⛁ need a dedicated migration
- ⛁¹ Migration in order for the live workspace to be publicly visible
./flow workspace:assignrole live "Neos.Flow:Everybody" viewer
- ⛁² (Optional!) Migration to fix copy of tethered nodes
./flow migrateevents:migratecopytetherednode
(This migration is only needed if replaying or the backend throws exceptions like: The NodeName must be set if the Node is tethered.
)
- ⛁³ (Optional!) Migration to reorder node removal events
# note the error "Writable events must contain at least one event" indicates the command was not required, sorry :D Everything is okay ^^
./flow migrateevents:reordernodeaggregatewasremoved
(This migration is only needed if replaying does not work and throws exceptions like: Failed to move node "000000000" in sub graph 000000000 because it does not exist
or Cannot update node with copy on write since no anchor point could be resolved for node 000000000 in content stream 000000000
)
NOTE the migration will cause all workspaces to be outdated and contain the removed nodes again before synching. After synchronisation (rebase) this is fixed.
- ⛁⁴ Status check for legacy copy nodes events
Also note that as copy nodes has been refactored, the legacy copy nodes events must be published to the live workspace before the final release of Neos 9.
To detect those cases please use:
./flow migrateevents:copynodesstatus
Features
1.) Highlight Content Repository Privileges
Introduces basic security to the event sourced content repository
PHP Api changes
Adjustments to VisibilityConstraints
:
The method VisibilityConstraints::frontend()
was renamed to VisibilityConstraints::default()
.
But for the cases you have used VisibilityConstraints
at all - as mandatory argument for getSubgraph
you can now simplify that to use getContentSubgraph
directly:
before
$subgraph = $contentRepository->getContentGraph($nodeAddress->workspaceName)->getSubgraph(
$nodeAddress->dimensionSpacePoint,
$nodeAddress->workspaceName->isLive() ? VisibilityConstraints::frontend() : VisibilityConstraints::withoutRestrictions()
);
after
$subgraph = $contentRepository->getContentSubgraph($nodeAddress->workspaceName, $nodeAddress->dimensionSpacePoint);
Note that getContentGraph(...)->getSubgraph(...)
still works but is only meant to be used if your you want to determine the VisibilityConstraints
for some case differently.
Usage
Workspace Permissions
The following workspace roles exist:
VIEWER
: Can read from the workspace- By default, everybody is a
VIEWER
to thelive
workspace
- By default, everybody is a
COLLABORATOR
: Can read from and write to the workspaceMANAGER
: Can read from and write to the workspace and manage it (i.e. change metadata & role assignments)
Furthermore, personal workspaces can be owned by a particular user. The workspace owner implicitly has the MANAGER
role, i.e. has full access to that workspace.
Workspace roles are transitive. That means that
COLLABORATOR
has all privileges of theVIEWER
andMANAGER
has all privileges of theCOLLABORATOR
To publish changes to a workspace, the authenticated user has to have at least the VIEWER
role on the workspace to publish and COLLABORATOR
role on the target workspace.
Workspace role assignments will be changeable with the new workspace module or via CLI:
./flow workspace:assignrole
ReadNodePrivilege
In general, the ReadNodePrivilege
works like it did before Neos 9: It allows to completely hide sub trees of the content repository from a given user group.
But the implementation and configuration format has changed.
This is how a ReadNodePrivilege
can be configured via Policy.yaml
:
privilegeTargets:
'Neos\Neos\Security\Authorization\Privilege\ReadNodePrivilege':
'Neos.Demo:ReadBlog':
matcher: 'blog'
The matcher
refers to a SubtreeTag
, so this example would hide all nodes that are tagged with blog
(including their descendants) from all users that don’t have a GRANT
on that specific privilege target.
By default, the privilege is active for all configured content repositories. By prefixing the matcher with
<content-repository-id>:
this can be limited to a specific CR (for exampledefault:blog
)
EditNodePrivilege
Likewise the purpose of the EditNodePrivilege
is like before Neos 9: To restrict certain users from changing nodes (includes creation, setting properties or references, disabling/enabling, tagging and moving, …) in a given subtree.
The new configuration syntax is similar to the one for ReadNodePrivilege
:
privilegeTargets:
'Neos\Neos\Security\Authorization\Privilege\EditNodePrivilege':
'Neos.Demo:EditBlogNodes':
matcher: 'blog'
Again, the matcher
refers to a SubtreeTag
, so this example would disallow users without a corresponding GRANT
permission to edit nodes in the subtree that is tagged blog
.
Both privileges expect a subtree to be tagged. That is not yet possible via the Neos UI or CLI but requires interaction with the PHP API (
$contentRepository->handle(TagSubtree::create(....))
) – we’ll provide a way to do that, follow #3732 for updates
Removed privilege types
The following Content Repository privilege types have been removed because their behavior was inconsistent and/or because they led to (performance) issues: NodeTreePrivilege
, CreateNodePrivilege
, ReadNodePropertyPrivilege
, EditNodePropertyPrivilege
We will most probably re-add some of the functionality in a future version, but for now you can implement the AuthProviderInterface in order to enforce custom authorization requirements.
Examples
Disallow a role to edit nodes of a subtree
With the following Policy.yaml
:
privilegeTargets:
'Neos\Neos\Security\Authorization\Privilege\EditNodePrivilege':
'Neos.Demo:EditBlogNodes':
matcher: 'blog'
roles:
'Neos.Neos:Administrator':
privileges:
-
privilegeTarget: 'Neos.Demo:EditBlogNodes'
permission: GRANT
only administrators are allowed to edit nodes in the blog
subtree.
The Neos UI does not currently properly reflect readonly nodes – The inspector will be empty and inline editable fields will be editable – but changing their content will lead to an AccessDenied exception
In order to also hide the uneditable subtree, the following can be added:
privilegeTargets:
# ...
'Neos\Neos\Security\Authorization\Privilege\ReadNodePrivilege':
'Neos.Demo:ReadBlogNodes':
matcher: 'blog'
roles:
'Neos.Neos:Administrator':
privileges:
# ...
-
privilegeTarget: 'Neos.Demo:ReadBlogNodes'
permission: GRANT
Allow a role to only edit within a given subtree
To achieve the opposite of the above, granting a user group to only edit nodes within a subtree, the whole tree must be tagged (i.e. the homepage node, all descendants will inherit the tag).
With all nodes being tagged demosite
and the blog nodes beeing tagged blog
in addition, the following Policy.yaml
will do:
privilegeTargets:
'Neos\Neos\Security\Authorization\Privilege\EditNodePrivilege':
'Neos.Demo:EditAnyNode':
matcher: 'demosite'
'Neos.Demo:EditBlogNodes':
matcher: 'blog'
roles:
'Neos.Neos:Administrator':
privileges:
-
privilegeTarget: 'Neos.Demo:EditAnyNode'
permission: GRANT
'Neos.Neos:Editor':
privileges:
-
privilegeTarget: 'Neos.Demo:EditBlogNodes'
permission: GRANT
With that, the administrator will be able to edit any node, but editors can only edit nodes within the blog
subtree.
(thanks bastian for the great documentation <3)
2.) Overhauled Node Copying
The new service copies the specified source node and its children to the target node
Note about dimensions
Currently the copying is primitive as that we take the read-model of the dimension to copy (the subgraph). and paste that into the target dimension.
That means that the copy does not alter other dimensions and that virtual variants are materialised.
For more information see {@link BUG: CopyNodesRecursively vs Content Dimensions · Issue #5054 · neos/neos-development-collection · GitHub}
Note about constraints
As we cannot rely on the full integrate on the subgraph regarding the current node type schema it might not be possible to copy a node and its children.
For example copying a node with tethered children that is not tethered according to the current node type schema, or copying properties that are not defined
in the current node type schema anymore. In those cases the structure adjustments have to be executed. (todo only copy what is applicable and be graceful)
Note about partial copy on error
As the above mentioned constraints can fail and we handle the determined content repository commands one by one, a failure will lead to a partially evaluated copy.
The content repository is still consistent but the intent is only partially fulfilled.
PHP Api changes
Instead of using CopyNodesRecursively::createFromSubgraphAndStartNode
and handling that in the CR, please use:
#[Flow\Inject()]
protected NodeDuplicationService $nodeDuplicationService;
// ...
$this->nodeDuplicationService->copyNodesRecursively(
$contentRepositoryId,
$workspaceName,
$sourceDimensionSpacePoint,
$sourceNodeAggregateId,
$targetDimensionSpacePoint,
$targetParentNodeAggregateId,
$targetSucceedingSiblingNodeAggregateId
);
3.) Highlight High level site import
- !!! FEATURE: High level Neos site import
site:importAll
- FEATURE: Allow mapping of legacy root paths to RootNodeAggregate NodeTypeNames
Add commands site:importall
, site:exportall
and site:pruneall
to import export and prune all sites of the given content repository.
This will export events files and sites into a package (Resources/Private/Content) or any other specified target directory.
For example importing the Neos Demo looks like
./flow site:importall --package-key Neos.Demo
The previously available commands cr:import
, cr:export
and cr:prune
were removed because those did not take the site nodes into account.
Additionally, the command ./flow cr:migrateLegacyData
was renamed and behaviour changed. In order to migrate Neos 8.3 to Neos 9.0 please use:
# the following config points to a Neos 8.0 database (adjust to your needs)
./flow site:exportlegacydata --path ./migratedContent --config '{"dbal": {"dbname": "neos80"}, "resourcesPath": "/path/to/neos-8.0/Data/Persistent/Resources"}'
# import the migrated data
./flow site:importall --path ./migratedContent
4.) Extension point to hook into command handling
- FEATURE: Command Hooks
- !!! TASK: Serializable Commands
- Neos Ui Adjustments
- TASK: Guards against recursion in get content repository and memory overflow
With custom projections and CatchUpHooks
we already provide two clean extension points.
With command hooks we provide a way to modify a command before it is handled.
Previously this was possible with the Signal/Slot mechanism for nodes (e.g. nodePropertyChanged
).
Common use cases are:
- enforcing unique properties
- adding some custom version numbering for imports
- calculating derived properties
And example implementation of the CommandHookInterface
can be found in the Neos Formbuilder package, the UniqueIdentifierCommandHook
see FEATURE: Ensure unique form element identifier with a CommandHook by dlubitz · Pull Request #142 · neos/form-builder · GitHub
5.) Improve catchup hooks
- !!! TASK: Catchups will only be able to access the state of the projection they are registered for
- TASK: Improve removal of asset usages on node removal
- FEATURE: Speedup content cache flush by using cte in
findAncestorNodeAggregateIds
Improves the performance of the asset usage and content cache catchup hook by introducing the query findAncestorNodeAggregateIds
.
Additionally the wiring for custom catchup hooks changed, please adjust accordingly.
Bugfixes
Neos Content Repository
- BUGFIX: Re-introduce stricter checks for subtree en/disabling and tagging
- ⛁³ BUGFIX: Migration to correct order of removed node events
- BUGFIX: Ensure users content stream is never left closed after publication