Adding a custom permission to a product

by Kees Hink last modified Nov 11, 2011 11:53 AM
Using rolemap.xml to create new Roles is easy, you can add predefined permissions to your new roles. But what if you want to define a new permission for your product? Use setDefaultRoles.

Note for Plone 4

Please note that this instruction target Plone 2.5 and Plone 3. In Plone 4, you can add permissions from ZCML directives: Please see this link. Or this one.

Purpose

Let's say you are developing a product called MyProduct, in which you want to create a new permission called "MyProduct: MyPermission".

Prerequisities

This how-to is targeted at product developers.

Step by step

  1. Add a file called permissions.py.
    from Products.CMFCore import permissions as CMFCorePermissions
    from AccessControl.SecurityInfo import ModuleSecurityInfo
    from Products.CMFCore.permissions import setDefaultRoles
    
    security = ModuleSecurityInfo('MyProduct')
    
    security.declarePublic('MyPermission')
    MyPermission = 'MyProduct: MyPermission'
    setDefaultRoles(MyPermission, ())
  2. Call this from your __init__.py.
    # Initial permissions setup.
    import permissions

The old way

There's been talk of Extensions/Install.py going away, so i'd advise against using this in your product.

Add this to your product's Extensions/Install.py:

from Products.CMFCore.permissions import setDefaultRoles

def install(self, reinstall=False):    
    setDefaultRoles('MyProduct: MyPermission', ())

 

Further information

Assigning permissions to a role using Generic Setup

If you also want to assign this permission to a role, 'Member' for example, the best way to go is to do it via Generic Setup in rolemap.xml:

<?xml version="1.0"?>
<rolemap>
  <roles>
    <role name="Member"/>
  </roles>
  <permissions>
    <permission name="MyProduct: MyPermission" acquire="False">
      <role name="Member"/>
    </permission>
  </permissions>
</rolemap>

As 'Member' is a default role, there is no need to include it in <roles />. If you want a custom role 'MyCustomRole' in your product, you could replace 'Member' by 'MyCustomRole' and be done.

Assigning permissions to roles the OLD way

Before Generic Setup, people used to assign permissions to roles in this way:

In Install.py:

from Products.CMFCore.permissions import setDefaultRoles

def install(self, reinstall=False):
    MY_PERMISSION = 'MyProduct: MyPermission'
    setDefaultRoles(MY_PERMISSION, ())
    PERMISSIONS = [
       (MY_PERMISSION, ['Member',], 0),
    ]
    for p in PERMISSIONS:
        self.manage_permission( p[0], p[1], p[2],)

Assigning permissions to roles the OLD way, several files

To cleanly seperate the code from the rest of your installation code, some people also spread it out over several files:

In permissions.py:
from Products.CMFCore.permissions import setDefaultRoles
from AccessControl import ModuleSecurityInfo
security = ModuleSecurityInfo('Products.MyProduct.permissions')
security.declarePublic('MY_PERMISSION')
MY_PERMISSION = 'MyProduct: MyPermission'
setDefaultRoles(MY_PERMISSION, ())
In AppConfig.py:
from Products.MyProduct.permissions import MY_PERMISSION
PERMISSIONS = [
   (MY_PERMISSION, 0, ['Member',]),
]
In Extensions/AppInstall.py:
from StringIO import StringIO
from Products.MyProduct.AppConfig import PERMISSIONS
def install(self):
    out = StringIO()
    for p in PERMISSIONS:
        self.manage_permission( p[0], p[1], p[2],)
    return out.getvalue()
In Extensions/Install.py:
from Products.ExternalMethod.ExternalMethod import ExternalMethod
    # try to call a custom install method
    # in 'AppInstall.py' method 'install'
    try:
        install = ExternalMethod('temp', 'temp', PROJECTNAME+'.AppInstall', 'install')
    except NotFound:
        install = None