Refactor permissions, ACLs, capabilities
Some ACL capabilities are maybe superfluous, some others are missing. Behaviour needs clear definition.
Collection of stuff / discussion
This section is to discuss / collect stuff we need to consider before deciding about a plan.
ACL capabilities not making sense
- if delete is implemented by storing an empty revision (like it is done in moin 1.9):
- delete ("write" is enough, if someone may write to a page, like replacing its content with "foo bar", this is not that different from deleting it)
ACL capabilities missing
- create (creating an item with a new name in the namespace)
- removeitem (removing an item COMPLETELY)
- dangerous. possible?
- removerevision (removing a revision from an item)
- dangerous. possible?
- move (rename an item)
- if delete will be implemented by moving objects to Trash/*, it is quite like move
- move = create (new item), read (all revs of old item), write (all revs to new item), remove (old item)
- if some user is allowed to create (a new item, giving it some name), he usually should be also allowed to move it (e.g. in case he made a typo in the name)
- copy (copy an item)
- similar to move, but without removing original item
- history (be able to see history / non-current revisions of an item)?
This section is about stuff we have discussed enough and decisions we have already made:
When accessing an Item (where accessing means (read/write/...) the users privileges are matched against the most recent revision's ACL (even if that revision is "deleted").
Plan: "read" behaviour
If the user may not read the most recent revision, he may not read the item at all.
Plan: "write" behaviour
Seems simple. If the user may not write (checking the latest revision's ACL), he may not write to that item at all. Old revisions can't be altered by design at all anyway.
Plan: "admin" behaviour
Plan: "rename" behaviour
Do we need a seperate privilege here? If we had such a privilege, we could just pass the rename command down to the storage API. That would just rename the item. (But we'd likely need to store a new rev indicating the name change). Another idea is to base this on already existing privileges. I.e.: May read src, may write src, may create & write to target. (Although that does not "nuke" the old item.)
Plan: "delete" behaviour
For delete we have two suggestions:
- Keep it as it is, i.e. store an empty body, set a deleted flag and keep the item where it is.
- Transfer the deleted item into a special $$TRASH$$ or Trash/ namespace
Plan: kill "revert" capability
"revert" can't be checked on storage layer, all the storage layer is seeing is a read access to some old revision and a create/write access to a new revision - thus read/write capability replaces "revert". From a high level permission perspective, "revert" has been pretty useless, because if someone could copy&paste an old revision's content into editor and save, this is not different from reverting it.
no problem on ACL level, can be easily replaced by "read" and "write"
content migration script needed, needs to just remove "revert" from existing ACLs (likely read,write is already there)
Plan: create capability
A privilege to create new pages. If the right is not given to a user and he has write rights he could edit existing pages.
How about adding an option for preventing unknown users (unwelcome bots that are not logged in) from reading any of the underlay pages? -- RogerHaase 2008-11-16 21:32:35
There is no benefit to the bot nor to my site for indexing the underlay pages, the bot would be better off indexing the underlay pages on the moin wiki. At least one unidentified bot goes straight for the TitleIndex page (ignoring the robots.txt file) and then grabs pages that I would rather not have indexed. While I could easily edit the ACL rule on the TitleIndex, WordIndex, SystemInfo, etc. pages to make them not readable by bots, doing so makes migrating to new moin releases one step harder. If there were a means of making all underlay pages subject to a configuration ACL rule, the redundant #acl -All:write Default rule in every underlay page could be eliminated. I do not consider this a high priority, just an alternative feature to consider when refactoring the ACL code. Another possible feature is to be able to configure ACL rules for classes of pages, such as page categories.
Since 1.8 underlay pages have the rights from acl_rights_default by #acl -All:write Default inherited.
- Yes, but the request is for a means of preventing non-logged in users from reading the underlay pages, but allowing non-logged in users to read the local wiki pages.
"create" Right and Subpages
Summary: The "create" right, by itself, does not address the practical need of protecting a parent page while allowing subpages to be created and modifiable. -- JohnMarshall, 2009-11-08 18:39:41
Update: Some additional "Possible Solutions" given. -- JohnMarshall, 2009-11-09 02:39:13
The following discussion assumes the acl_hierarchic=True.
Without a "create" right (e.g., <=v1.9), it is necessary for a user to have "write" right in order to create subpages. This is a problem if one wants to allow the creation of subpages but disallow modification of the parent page. From what I can understand, there is no way to accomplish this using the current rights system.
Current practice may involve manual intervention in order to achieve the desired results. This should be supported automatically by MoinMoin.
With "create" Right
With the addition of the "create" right, we can protect the parent page and allow the creation of subpages by setting the parent page with "#acl bob:read,create". There remains a problem, though. This allows the user one opportunity to put content into the subpage, i.e., at create time. Because there is no "write" right in the parent page, subpages are immutable. To add a "write" right to the parent page is not an acceptable solution if the parent page must be immutable.
- If a user is allowed to create a subpage, then he is allowed to set the acl line at creation only. This would allow the user to set the acl line as needed, possibly including the "write" right, and possibly the "admin" right if appropriate.
- This solves the problems described but makes it impossible to limit the user who creates the subpage which may be appropriate/required in some cases.
Solution #1 with support for an additional page pragma: #acl_mask (and perhaps an acl_rights_create_mask configuration setting). The acl_mask would limit what acl settings could be set in the created subpage. The default may be #acl_mask admin which would mask out the "admin" right (for any user or group) from the created subpage.
- This solves the problems described and allows the parent page admin to control what acls subpages are allowed to be created with (at creation time only). Of course, without the "admin" right (i.e., because it was masked out), the user who created the subpage could not further modify the subpage acl. However, if being able to modify the acl is meant to be allowed, it should not be masked out to begin with.
Solution #2 but with support for a special user 'Mask' in the #acl ... line.
Using 'Mask' instead of #acl_mask leverages the current Acl code and objects, and also does not add another pragma which would have to be protected against modification by user without "admin" rights.
Solution #3 but with a "~" modifier. The ~ modifier would mark "mask" settings. This would provide the ability to tailor rights masks to specific users. For example, for the example above, the acl line with a mask modifier could be extended to "#acl bob:read,create ~bob:admin". This would mean user bob has "read" right to the parent page, "create" right for subpage, but if he did set an acl, "admin" would be masked out.
- Allows targetted mask settings, does not required new structures. Mask information as easy to extract as acl information.
Solution #3 but with mask information encoded in the individual acl settings and an inline modifier "~". For example, to mask out "admin" right for bob: "#acl bob:read,create,~admin".
- Same benefits as #4, but groups mask information with acl. No extra code required if "~admin" treated as an acl "right" (although it really is not).
Solution #3, but with mask information appended to the individual acl settings (":" used as separator). The bob example would be "#acl bob:read,create:admin"
- Same benefits as #5, but clearly separates acl from mask. Requires extra support in code.
Well, my stomach feeling about above is that it is too complicated and mixing up things:
- the current acl system is already beyond many user's comprehension, I see often rather strange acl lines. people are rather guessing what stuff does and not reading the help page (or not understanding it fully). while this is not necessarily the fault of moin or its acl system, making it even more complex doesn't sound like a good idea. We also had coding errors now and then in the ACL code, the same thing applies there: the more complex, the more error prone.
- if the "create" right gives also a "one time permission to set acls", it mixes up permissions. it is not just "create", but also "write" and "admin". the current system tries to avoid "composite" permissions, stuff is rather separate.
- if some user fails to get the ACLs right with the first save (e.g. giving himself write permissions), he would have same problem as without create and he wouldn't be able to fix it without an admin's help. Of course this is already similar for people who get "admin" permission (but not from acl_rights_before), but otoh, ADMINs are expected to get it right (and being able to shoot themselves in their feet), but if you have "create" for rather normal users modifying ACLs, you maybe can't expect them getting it right at once (and maybe they are also not used to being able to shoot themselves in their feet).
- so, while I see the problem you are trying to solve, I have doubts whether the proposed solution would be an overall improvement
please note that moin does not only have ACLs and ACL rights, but also a thing called "SecurityPolicy" which enables one to implement complex behaviour. See the autoadmin secpol example (maybe the problem described above could be solved in a similar way?).
-- ThomasWaldmann 2009-11-24 14:48:19
In a traditional filesystem, you have two types of objects: directories and files. Permissions on directories have different symantics than permissions on files, allowing for many permutations. MoinMoin does away with the "directory" concept, but still allows subpages, which gives each page a dual identity as both a "file" and a "directory". I like this MoinMoin paradigm, but it has led to the particular problem discussed here. The most usable solution might be to add another directive, perhaps called "#aclhere". #aclhere would always be checked first for a particular page, but in hierarchical mode, would be skipped when searching for subpage permissions. The advantage to this solution is that it doesn't change the existing usage much, while solving problem under discussion. To allow creation of read/write subpages, the permissions would go like this:
#acl SubpageEditors:create,read,write,delete,revert #aclhere All:read
-- pooryorick 2010-03-25 02:28:00
I have not checked through the code supporting page rename/copy/move, but it would need to check the parent page acl settings before allowing a page to be renamed/copied/moved to a subpage position.