Custom privilege types in real life projects

Playing around with a custom privilege type I think we hit an implementation limit, or at least I think we can improve the implementation.

Let me first explain the usecase I have seen in different projects now:

  • Every account logging on to the website gets his own profile page which is implemented as a node
  • This node is then used for making references to other pages, like groups of people, departments, and so on
  • Based on the relation of that person to for example a group certain nodes should have read restriction

So in short: limit read access to node of type ‘My.Package:InternalPage’ if the ‘profile page’ node has no reference to the parent of the ‘InternalPage’

It’s doable to create a custom privilege target for that. This should then for example look like:

privilegeTargets:
  'My\Package\CustomPrivilege':
    'My.Package:GroupInternalPages':
      matcher: 'nodeIsOfType("My.Package:InternalPage") && currentUserIsInParentGroup()'

Imagine this now all works. This matcher would now match a set of nodes based on the current security context. As such this specific resource is now protected as it is defined as privilegeTarget, so basically you’re done.

Done? Do I not need a GRANT or DENY? Nope, the opposite… If you add a GRANT for a role this privilege is granted and as such the sql generated by your custom privilege class is not taken into account which neutralizes the policy and will just give access to anybody.

I find this rather confusing tbh, but I feel like it is because using the current user from the security context inside of a matcher is wrong. When you do that you basically define a role (at runtime) that the user has. So probably it would be better to for example allow a configuration like:

privilegeTargets:
  'My\Package\CustomPrivilege':
    'My.Package:GroupInternalPages':
      matcher: 'nodeIsOfType("My.Package:InternalPage") && currentUserIsInParentGroup()'
roles:
  'My.Package:User':
    privileges:
      -
        privilegeTarget: 'My.Package:GroupInternalPages'
        permission: ${currentUserIsInParentGroup() ? 'GRANT' : 'DENY'}

I know multiple people have similar usecases in projects atm, like for example using dynamic roles, limiting site access and so on. So I’d really be curious to hear other experiences / opinions how we can improve this. Because the implementation I did now does not feel like a really nice integrator experience in this regard (although I really love the extensibility of the matchers :stuck_out_tongue: )

2 Likes

Hey Rens,

I have been thinking pretty much along the same lines (at least if I understood your question correctly :wink: ) while working on language-level editing restrictions for nodes: https://review.typo3.org/#/c/40420/.

I think you need to add another privilege target which matches all “InternalPages”. As soon as you add this privilegeTarget, it by default gets an abstain permission assigned, leading effectively to a deny if nothing has been added additionally.

So, if I understand your issue correctly, I believe the following should work for your use case:

privilegeTargets:
  'My\Package\CustomPrivilege':
    'My.Package:GroupInternalPages':
      matcher: 'nodeIsOfType("My.Package:InternalPage") && currentUserIsInParentGroup()'
    'My.Package:AllInternalPages':
      matcher: 'nodeIsOfType("My.Package:InternalPage")'
roles:
  'My.Package:User':
    privileges:
      -
        privilegeTarget: 'My.Package:GroupInternalPages'
        permission:  'GRANT'

Maybe @bwaidelich or @andi have some more thoughts to add – or maybe I totally misread the question and am on the wrong track. But maybe it also helps :smile:

All the best,
hear you soon,
Sebastian

Reading your comment you read the question correct :wink: For now I chose a different approach in the project, but will give this a try later on.

In the current situation it will still not work in production context btw as the query caching is only taking roles into account for the cache identifier (which makes sense), but in this case (user specific stuff) it’s a bit unfortunate :wink:

From integrator point of view: if your suggested approach would work, is that really the simplicity we aim for?

Hey Rens,

ah. Good point! I hope this is configurable at a central position – if not, we should do this…

I think the current complexity stems from the fact that until you define a privilege, things are not-access-restricted. As soon as you add one, it is “Denied by default”. Problem: We cannot automatically determine what you want to access-restrict on, so in your above case, we have no way of knowing that we only want to access-restrict InternalPage and not all nodes. Frankly, I personally wouldn’t know how to change the system to another structure which is more consistent. Any idea? :slight_smile:

I’v been discussing this with Andi recently as well; and we ended at the point that the policy.yaml is pretty low-level anyways; allowing all kinds of possible setups but being hard to configure at times. We thought that a graphical tool should handle this; and we would definitely need a “Policy Debugger” which hints at these kinds of issues I guess.

All the best,
Sebastian

Yes, I think so :wink: What I shortly display in the second code snippet would be a possibility. The resource definitions should imho not include account / role based selectors (at least not in my usecase) as they lead to some kind of dynamic role defined at runtime. That would belong to the ‘roles’ section of the configuration. That’s what (I think) makes the configuration unintuitive for this usecase. Usage of eel expressions (smartly cached) in the roles configuration could be a possible solution. But… more importantly: we should stick to the problem phase a bit :wink: So we should probably collect the usecases people work on now (I’ve 2 projects I work(ed) in, you worked on something, @aertmann has a project too I think, @andi also).

Maybe those usecases together lead to a completely different view on the problem.

Hi all,

thanks for the good explanations so far. I think all of you are right :slight_smile: Our use case goes more into the direction of defining dynamic roles during runtime. As we will be sitting together next week, I propose to collect the use cases and have a discussion session about that. It’s really nice to see the concepts in real world and I’m sure we’ll find good solutions for the current problems or configuration complexity!

1 Like

Sounds good, but don’t forget to post back the results of the discussion in this thread :wink: And ping me if you’ve any questions about my usecases during the discussions as I won’t be present next week.

ah too bad you’re not there. We’ll ping you and report back here for sure!

@andi Has this thread has not been update for a while, did you have some news ?

Yes please, I also struggled this weekend to explain how to use it with the usecase there was on Slack…

Hi,

we will be working on this project again in february and march. The solution we strive for is described in: Project proposal: Introduce parameterized roles

1 Like

Any news? :wink:

1 Like