Update the security API to bring it closer to a Rights API implementation

Hi all,

Short version:

Add a new interface ReadableSecurityRule in the security module, that extends SecurityRule with getRights(), getUsers() and getGroups(), and make all data returned by org.xwiki.security.authorization.internal.DefaultSecurityEntryReader return ReadableSecurityRule so that we can re-use the implementation in xwiki-platform-security-bridge as a framework to read rights set on different entities on the wiki.

Long story:

I’m working on an extension that should allow users to view & modify rights for a page. I did not find an api for doing this, and I don’t think we have a manner of handling rights (see https://jira.xwiki.org/browse/XWIKI-13466 ).

The current proposal only handles the usecase of reading existing rights, not writing them.

The security module is already defining some abstractization for the rights (as mentioned in XWIKI-13466) - the SecurityRule and the collection SecurityRuleEntry - and also contains a module to read the security rules / entries from the wiki data (documents and objects). Ideally, all code that needs to read rights should reuse this existing module: the org.xwiki.security.authorization.SecurityEntryReader component implemented in the xwiki-platform-security-bridge .

However, this abstractization only defines methods to check if a rule concerns a given predicate (right) or subject (user or group) but without actually providing the list of predicates of a rule or the list of subjects. Thus, it is not complete for the purpose of reading the set rights.

This proposal is about adding a new interface ReadableSecurityRule that would extend SecurityRule with 3 additional functions, dedicated to reading the data of the security rule: getRights(), getUsers() and getGroups() . The idea behind adding a new interface instead of modifying the existing one is to not break backwards compatibility. ReadableSecurityRule would be declared experimental until we settle about it (esp. given the write usecase that would need to be handled in the future).

All the classes that implement the SecurityRule interface in the xwiki-platform-security-bridge would be changed to implement the ReadableSecurityRule, so that the org.xwiki.security.authorization.SecurityEntryReader implementation can be used to fetch ReadableSecurityRule items (with a couple of casts). These classes are org.xwiki.security.authorization.internal.XWikiSecurityRule and org.xwiki.security.authorization.internal.AllowEditToNoOneRule .

Note: the SecurityRuleEntry should / could also be improved/changed to handle ReadableSecurityRule items, but for now it is just a simple collection and the logic can be re-done if needed, with casts on the caller side. A further proposal can be done for that.

WDYT about:

  1. the idea that, for achieving https://jira.xwiki.org/browse/XWIKI-13466, the abstractization of the security module is to be extended and used; otherwise put, a new abstractization should not/needs not be created. Along with this, the implementations of the security modules (bridge and other) can be extended to cover the needs for read/write and used instead of creating new ones dedicated to reading / writing rules (if reasonable, we’d always prefer having separate services, for example for some of the write operations, but when not possible we’d need to extend the security model bridge).
  2. adding the new interface in the security module to make the rules read by the bridge usable to get information about rights and not only to check them.
    1. is ReadableSecurityRule a reasonably correct name?
  3. changing the implementation of the xwiki-platform-security-bridge to return Readable data, not only match-able like it is today.


We could indeed come up with an interface extending SecurityRule for the special kind (but still conceptually generic enough) of rules which contains user, groups and rights. Now ReadableSecurityRule is a way too generic name, keep in mind that this is only one kind of SecurityRule, the others are readable too but they are not based on the same criteria. Maybe an easier way to find the right name is actually to have several: a UsersSecurityRule, a GroupsSecurityRule, a RightsSecurityRule all implemented by XWikiSecurityRule. The reason I propose to separate that in different concepts that each implementation of SecurityRule can pick is that for example XarSecurityRule and AllowEditToNoOneRule could implement RightsSecurityRule but users and groups don’t make sense for those (and there is probably others implementations of SecurityRule out there).

bq. make all data returned by org.xwiki.security.authorization.internal.DefaultSecurityEntryReader return ReadableSecurityRule

That’s not possible since DefaultSecurityEntryReader is actually more generic than XWikiSecurityRule but I guess what you mean is that some of the rules returned by DefaultSecurityEntryReader would implement an interface which expose users, groups and right and you would just need to cast them.

Wdym users and groups don’t make sense for those? AllowEditToNoOne actually makes perfect sense, it’s even in the name (noOne -> getUsers() = getGroups() = emptyList).

More generically, and also to answer this

SecurityRule has the 2 functions match(user) and match(groups) so from a mathematical point of view it is possible to translate that into getters -> getUsers() = the list of all the users for which match(user) returns “true”, same for getGroups(). It may not always be that simple to implement (getting the whole list in advance versus answering the question of whether it matches or not) but from a logical and mathematical point of view I don’t see how those getters are not equivalent to SecurityRule.