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
and you can view these on the Sharing tab
and in ZMI Security tab.
Good introduction to roles: Basic Roles and Permissions in Plone
New Plone roles can be created through the GenericSetup rolemap.xml file.
<?xml version="1.0"?> <rolemap> <roles> <role name="National Coordinator"/> <role name="Sits Manager"/> </roles> <permissions> </permissions> </rolemap>
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="Sits Coordinator" title="Is a sits 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.
manage_setLocalRoles is defined in AccessControl.Role.RoleManager.
context.manage_setLocalRoles(userid, ["Local roles as a list"])
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()
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])
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 tool via the ZMI.
Please see the zopyx.plone.cassandra add-on product.