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'
implements(IPropertiesPlugin)
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(self.id, 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:
RESPONSE.redirect('manage_workspace')
manage_addGroupAliasPluginForm = DTMLFile('zmi/GroupAliasPluginForm',
globals(),
__name__='manage_addGroupAliasPluginForm')
And in __init__.py:
from AccessControl.Permissions import add_user_folders
from Products.PluggableAuthService import registerMultiPlugin
from ... import groupalias
registerMultiPlugin(groupalias.GroupAliasPlugin.meta_type)
def initialize(context):
"""Initializer called when used as a Zope 2 product."""
context.registerClass(groupalias.GroupAliasPlugin,
permission=add_user_folders,
constructors=(groupalias.manage_addGroupAliasPluginForm,
groupalias.manage_addGroupAliasPlugin),
visibility=None)
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 setuphandlers.py like this:
def addGroupProperties(context):
""" Add a GroupDataPlugin to acl_users and add property to
portal_groupdata
"""
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:
log.info("%s already installed." % pluginid)
else:
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):
continue
pas.plugins.activatePlugin(interface, plugin.getId())
pas.plugins.movePluginsDown(
interface,
[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._delProperty('alias')
gd_tool._setProperty('alias', '', 'string')