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
Editor, etc. and you can view these on the
Sharing tab and in
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.
is defined in
context.manage_setLocalRoles(userid, ["Local roles as a list"])
method returns currently-set local roles. This does not
return all the effective roles (which may include
roles acquired from the parent hierarchy).
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()
takes a list of usernames as argument. All local
roles for these users will be cleared.
The following example (
membrane-specific) 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])
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
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
Products.PlonePAS.plugins.role.GroupAwareRoleManager.getRolesForPrincipal(). There you see how roles for a given context are being
tool via the
Please see the zopyx.plone.cassandra add-on product.