Creating and setting local roles of Plone members programmatically.
Local roles allows user accounts to have special privileges for a folder and its children.
By default Plone has roles like
You can view these on the Sharing tab and in the Management Interface Security tab.
Good introduction to roles: Basic Roles and Permissions in Plone
Creating a new role¶
New Plone roles can be created through the GenericSetup rolemap.xml file.
<?xml version="1.0"?> <rolemap> <roles> <role name="National Coordinator"/> <role name="Site Manager"/> </roles> <permissions> </permissions> </rolemap>
Adding a role to the Sharing Tab¶
To let the newly created role appear in the @@sharing tab, create a GenericSetup sharing.xml file.
<sharing xmlns:i18n="http://xml.zope.org/namespaces/i18n" i18n:domain="plone"> <role id="Site Manager" title="Is a site coordinator" permission="Manage portal" i18n:attributes="title" /> </sharing>
The title is the name to be shown on the sharing page. The required_permission is optional. If given, the user must have this permission to be allowed to manage the particular role.
Setting local role¶
manage_setLocalRoles is defined in AccessControl.rolemanager.RoleManager.
context.manage_setLocalRoles(userid, ["Local roles as a list"])
Getting local roles¶
get_local_roles() method returns currently-set local roles.
This does not return all the effective roles
(which may include roles acquired from the parent hierarchy).
get_local_roles_for_userid() returns roles for a particular user as a tuple.
# get_local_roles() return sequence like ( ("userid1", ("rolename1", "rolename2")), ("userid2", ("rolename1") ) roles = context.get_local_roles()
getRolesInContext() method returns the list of roles assigned to the user, including local roles assigned in the context of the passed-in object and both local roles assigned directly to the user and those assigned to the user’s groups.
from Products.CMFCore.utils import getToolByName pm = getToolByName(context, 'portal_membership') roles_in_context = pm.getAuthenticatedMember().getRolesInContext(context)
Deleting local roles¶
manage_delLocalRoles(userids) takes a list of usernames as argument.
All local roles for these users will be cleared.
The following example (
will reset local roles based on external input
def _updateLocalRoles(self): """ Resets Local Coordinator roles for associated users. Reads Archetypes field which is a ReferenceField to membrane users. Based on this field values users are granted local roles on this object. """ # Build list of associated usernames usernames =  # Set roles for newly given users for member in self.getExtraLocalCoordinators(): # We are only interested in this particular custom membrane user type if member.getUserType() == "local_coordinator": username = member.getUserName() usernames.append(username) self.manage_setLocalRoles(username, ["Local Coordinator"]) membrane = getToolByName(self, "membrane_tool") # Make sure that users which do not appear in extraLocalCoordinators # will have their roles cleared for username, roles in self.get_local_roles(): sits_user = membrane.getUserAuthProvider(username) if not username in usernames: print "Clearing:" + username self.manage_delLocalRoles([username])
Blocking local roles¶
Local roles may need to be blocked on a particular object by default. This can be achieved by add a flag to your content object, like so:
class MyType(content.Container): """My content type """ implements(IMyType) __ac_local_roles_block__ = True
Local role caching¶
Resolving effective local roles is a cumbersome operation, so the result is cached.
Unit testers: Local roles are cached per request. You need to clear this cache after modifying an object’s local roles or switching user if you want to get proper readings.
Unit test example method:
def clearLocalRolesCache(self): """ Clear borg.localroles cache. borg.localroles check role implementation caches user/request combinations. If we edit the roles for a user we need to clear this cache, """ from zope.annotation.interfaces import IAnnotations ann = IAnnotations(self.app.REQUEST) for key in list(ann.keys()): # Little destructive here, deletes *all* annotations del ann[key]
Set your breakpoint in
There you see how roles for a given context are being resolved.
acl_users.portal_role_manager via the Management Interface.
Please see the zopyx.plone.cassandra add-on product.