Hi folks, I decided to do an analysis of how exactly how permissions are checked so we might be able to brainstorm about where there is low hanging fruit in the optimization field.
0. Check that the user is authenticated 1. If user is attempting write operation on read-only wiki, return false. 2. If user is a guest, get XWikiPreferences for the wiki and do 4 checks on the XWikiPreferences object to see if the action requires authentication. 3. If action is "delete", get current document and check if current user created that document. 4. Determine if user is superadmin 5. Load DocumentReferenceResolver from ComponentManager and normalize username then compare to superadmin name. 6. Check for admin status on main wiki 7. Get XWikiPreferences document for main wiki 8. scan for rights objects which allow the user "admin" permission, return if found 9. get list of all groups which user is a member of, repeat check for each, returning if found 10. If checking permission for "programming" then repeat from step 7 with "programming" as permission. 11. If the permission being checked is programming, return the result even if false. 12. If in a subwiki, get the XWikiServer<subwiki> document and return if the current user is the owner. 13. If checking for register permission then get the XWikiPreferences document for the wiki. 14. scan for rights objects which allow the user, return if found 15. get list of all groups which user is a member of, repeat check for each, returning if found 16. if no match is found, check for deny rights on the user, return if found 17. get list of all groups which user is a member of, repeat check for each, returning if found 18. Get XWikiPreferences from wiki 19. scan for rights objects which allow the user "admin" permission, return if found. 20. get list of all groups which user is a member of, repeat check for each, returning if found 21. Get WebPreferences for space where document to check permissions resides. 22. scan for rights objects which allow the user "admin" permission, return if found. 23. get list of all groups which user is a member of, repeat check for each, returning if found 24. if the WebPreferences document specifies another Space as it's "parent" then change to that space and return to step 21. 25. Get the document to check permission on 26. scan for rights objects which deny the user, return if found 27. get list of all groups which user is a member of, repeat check for each, returning if found 28. scan for rights objects which allow the user, return if found 29. get list of all groups which user is a member of, repeat check for each, returning if found 30. Get the WebPreferences document for the space where document to check permission on resides. 31. scan for rights objects which deny the user, return if found 32. get list of all groups which user is a member of, repeat check for each, returning if found. 33. scan for rights objects which allow the user, return if found 34. get list of all groups which user is a member of, repeat check for each, returning if found. 35. Check if the WebPreferences document specifies a "parent space" if so, change to that space and go to step 30. 36. Get the XWikiPreferences document for the wiki 37. scan for rights objects which deny the user, return if found 38. get list of all groups which user is a member of, repeat check for each, returning if found 39. scan for rights objects which allow the user, return if found 40. get list of all groups which user is a member of, repeat check for each, returning if found Getting the list of groups which a user is a member of is relatively quick after the first run since it is cached. After being loaded it is stored in the context but the implementation doesn't trust the version in the context and gets it again. It could be a little bit faster by just assuming that anything in the context is still valid. If a group is a member of another group then the checks will be repeated twice each time. One thought that comes to mind is that we could check permissions on a user and all of the groups of which he is a member, simultaneously. This would reduce the number of scans over the list of objects in a given document and since this is such a hotspot, I think optimizations like this might pay off. Documents which need to be loaded include: The XWikiPreferences for the main wiki XWikiPreferences for the subwiki (if applicable) WebPreferences for the space (and any space listed as a parent) The document which we are checking If in a subwiki, the XWikiServer<subwiki> document This means that for any level of performance, all documents other than the document we are checking need to remain in the cache perpetually. Since the vast majority of checks are for things like view and edit with users who don't have programming or admin permission, it makes sense to rearrange the checks so that the most common path executes the fastest. This would be a major project though. Any other thoughts and ideas about it? Caleb _______________________________________________ devs mailing list [email protected] http://lists.xwiki.org/mailman/listinfo/devs

