Coding, Scripting, Administration

A new property for groups

This took me a while to puzzle out: If you want your user groups in Plone to have a custom property (in my case an "alias" of type string), you create a PAS property plugin that implements IPropertiesPlugin.

from Products.PluggableAuthService.interfaces.plugins import IPropertiesPlugin
from Products.PluggableAuthService.plugins.BasePlugin import BasePlugin

class GroupAliasPlugin(BasePlugin):
""" Provides the property 'alias' for groups """
    meta_type = 'Group Alias Plugin'

Basically you only need to implement the method getPropertiesForUser. To make the property editable, it should return a MutablePropertySheet instance and you also should implement setPropertiesForUser.

from Products.PlonePAS.sheet import MutablePropertySheet
    def getPropertiesForUser(self, user, request=None):
        return MutablePropertySheet(, schema=[('alias', 'string'),], **data)

    def setPropertiesForUser(self, user, propertysheet):

Now we need to make out plugin addable via the ZMI:

from App.special_dtml import DTMLFile

def manage_addGroupAliasPlugin(self, id, title='',
                               RESPONSE=None, schema=None, **kw):
    """ Add a Group Alias Plugin. Comes with custard or ice cream """
    o = GroupAliasPlugin(id, title, schema, **kw)
    self._setObject(o.getId(), o)

    if RESPONSE is not None:

manage_addGroupAliasPluginForm = DTMLFile('zmi/GroupAliasPluginForm', 

And in

from AccessControl.Permissions import add_user_folders
from Products.PluggableAuthService import registerMultiPlugin
from ... import groupalias


def initialize(context):
    """Initializer called when used as a Zope 2 product."""

We're almost there. To use the plugin, you have to add it to acl_users and activate it, AND you have to tell portal_groupdata that it should handle an additional property. If you want it active by default, you can do it in like this:

def addGroupProperties(context):
    """ Add a GroupDataPlugin to acl_users and add property to
    site = context.getSite()

    # most of this was borrowed from pas.plugins.ldap, thanks!
    pluginid = 'groupalias'
    pas = site.acl_users
    installed = pas.objectIds()
    if pluginid in installed:"%s already installed." % pluginid)
        plugin = GroupAliasPlugin(pluginid, title="Group Alias Plugin")
        pas._setObject(pluginid, plugin)
        plugin = pas[plugin.getId()] # get plugin acquisition wrapped!
        for info in pas.plugins.listPluginTypeInfo():
            interface = info['interface']
            if not interface.providedBy(plugin):
            pas.plugins.activatePlugin(interface, plugin.getId())
                [x[0] for x in pas.plugins.listPlugins(interface)[:-1]],

    # Our PAS property plugin already provides additional properties,
    # but we need to let portal_groupdata know about them.
    gd_tool = getToolByName(site, 'portal_groupdata')
    if gd_tool.hasProperty('alias'):
    gd_tool._setProperty('alias', '', 'string')
9th November 2014Filed under: Plone   user management   PAS