New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
FEATURE: Add new NodePrivilege matchers restrict editing a node if user is in a defined workspace #4884
base: 8.3
Are you sure you want to change the base?
Conversation
Hey @Benjamin-K ! Thanks for this change. This sounds more like a feature instead of a task. So your PR should target Neos 9.0 then 🙂 |
Hey @crydotsnake, You're right, this is kind of more of a feature. But as (IMO) the current implementation of What do you think? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks so much for taking care!
I added some inline comments, but more importantly I wonder:
- Should we add it to 8.3? I would vote for it since it is a really important improvement to make ACLs work (I would still not call it a "TASK" but a "FEATURE" which it clearly is)
- I wonder if it is a problem to inject the
UserService
into this context but I can't think of another way to get hold of the currently authenticated user (and s.th. likeuserIsInTargetWorkspace(current.userService.currentUser, "workspace-name")
in the Policy seems hacky, too - Can we come up with a test for this?
Neos.ContentRepository/Classes/Security/Authorization/Privilege/Node/NodePrivilegeContext.php
Outdated
Show resolved
Hide resolved
/** | ||
* Matches if the currently-selected workspace is the target workspace of the current user. | ||
* | ||
* Example: userIsInTargetWorkspace(['preview-1234']) matches if the current user |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not 100% sure about the naming tbh.
is the user really in the target workspace?
What about just isTargetWorkspace()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The also not 100 % sure. But isTargetWorkspace()
is not what this matcher will test IMO, as it is (in theory) a matcher on the node and not on the user.
We could use sth like canPublishToTargetWorkspace()
or sth. similar if we want to remove the user
. I'm in for new suggestions though.
public function userIsInTargetWorkspace($workspaceNames): bool | ||
{ | ||
if ($this->node === null) { | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems dangerous to me, but it's the same in the other matchers so it's probably fine to keep it here as well
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might really be a case, where accurate tests are needed. I wondered about that one, too.
Neos.ContentRepository/Classes/Security/Authorization/Privilege/Node/NodePrivilegeContext.php
Outdated
Show resolved
Hide resolved
Neos.ContentRepository/Classes/Security/Authorization/Privilege/Node/NodePrivilegeContext.php
Outdated
Show resolved
Hide resolved
Given that this for once is code that is completely ignored unless you actually use this Privilege I would be fine with adding it (with FEATURE) to 8.3. |
Thanks for your contribution. I have no problems when merging this little feature into 8.3 but the timing is a bit bad ^^ |
In regrads to:
I don't think this is "a thing". The user has no current dimesions, you have two directions you can go, which one is more correct depends I guess, a) parse dimensions from URL (again) and use those - I would prefer to NOT do that. |
You mean: A 3rd party package that provides a custom @Benjamin-K What do you think of that suggestion? |
I think, we could just leave this for now.
@kitsunet Would be nice, if that was the case. But it's actually not. Both,
We could do that. But right now, if one privilege (for example for the # Policy.yaml
privilegeTargets:
'Neos\ContentRepository\Security\Authorization\Privilege\Node\EditNodePrivilege':
'Vendor.Package:PrivilegeTargetOld':
matcher: 'isDescendantNodeOf("n0de-0001-0000-0000-111111111111")'
'Vendor\Package\Security\Authorization\Privilege\Node\EditNodePrivilege':
'Vendor.Package:PrivilegeTargetNew':
matcher: 'isDescendantNodeOf("n0de-0002-0000-0000-222222222222") && customMatcher(['workspace-abcd'])' I think we have to create multiple new privilege classes, one for each existing privilege class in Neos.ContentRepository/Classes/Security/Authorization/Privilege/Node/.... Not sure, if I want that "much" code for such a little addition.
I would really like to have tests for this feature. And for the other node privileges as well, as they are also missing 🫣 I will try to add a test, but first need to figure out, how to get all the required context values (UserService with a mocked user, a mocked node, ...). |
@Benjamin-K then I would like to understand your testcase better because if the context says live then you should be seeing live, it is never node specific. |
@kitsunet Let's say, you are logged in and work in workspace "Preview", but have not done any changes so far. If I get you right, This currently is not the case and will return "live" until some user pushed some changes to the "Preview" workspace. The problem with this is: Currently you cannot allow a user to only work in a specified workspace ("Preview" in this example) without having some other user (with more privileges) pushing changes to that workspace. It's actually not about what a user sees (which is "live"), but what a user wants to achieve (make changes to a node in "live" workspace and push them to the "Preview" workspace). |
It absolutely must, what you describe as the behavior cannot work. I guess I will have to try and reproduce this to understand what is going wrong here.... |
@kitsunet Would be really nice, if that was the case, as most of this PR could be removed then. Currently both
return the same workspace – the one, the node is in, no matter which workspace the user is currently working in. |
I just had another look at the code, I think there is some very nasty conceptual dragons there. The ReadNodePrivilege eg. extends the EntityPrivilege. This is important because Node(Interface) is not an entity. The Entity is NodeData as ReadNodePrivilege also says. BUT
|
This is, what actually happens. BUT: The workspace of the NodeData table is holding the actual workspace of the node you want to edit. And that is the problem here. Let's say, i have switched to workspace So for me (let's say i am User A) to be able to read/edit/... a node:
|
This PR adds a new NodePrivilege matcher
userIsInTargetWorkspace
, that will check, if the user is in one of the given workspaces.There is an existing matcher
isInWorkspace
, but it does not handle that case in a totally correct way, as it will only match after the node has been edited and published to one of the defined workspace and therefore can raise some questions when editing a node that is (by default) in the live workspace and gets published to a restricted workspace workspace or (with a whitelist approach) the node can not be edited until some user with access to the node pushes the node to an allowed workspace.Example:
Setup:
Preview
live
Now a user with role
Vendor.Package:WorkspaceRole
won't be able to edit the node until a user with the required permissions publishes some changes to workspace "preview-abcd", while a user with roleVendor.Package:TargetWorkspaceRole
can.resolved: #3893
Upgrade instructions
If you previously used the
isInWorkspace
matcher, consider updating touserIsInTargetWorkspace
(unless the described behaviour above is really what you wanted).Review instructions
The behaviour above can also apply to the current implementation of the
isInDimensionPreset
matcher. This can be the case, if fallback rules are defined in the dimension settings. I will add this here, too, but first need to figure out how to get the current dimension of the user instead of the selected node.Checklist
FEATURE|TASK|BUGFIX
!!!
and have upgrade-instructions