Personal tools
You are here: Home Documentation Tutorials Understanding permissions and security Using permissions and workflow in your custom products
Support

Get Help

Join our chat rooms or support forums if you have more specific questions.

Plone Training
Learn how to design, build, and deploy a website in Plone through one of the numerous Plone training sessions around the world.
Find Plone training…
 
Document Actions

Using permissions and workflow in your custom products

When you are developing a Plone site, it is usually best to develop your customisations or new content types on the filesystem, as a new Zope product. Setting up workflows programatically using the portal_workflow tool is a bit of a pain, but luckily there are tools to make your life much easier. You also need to ensure you use the correct permission declarations on your objects.

Martin Aspeli

Plone uses a combination of low-level Zope permissions, roles, local roles and workflows to manage permissions on objects. Understanding these will help you manage how, and by whom, your Plone site is accessed.
Page 5 of 5.

Explaining how to develop products and secure them properly is beyond the scope of this tutorial. Suffice it to say that to create re-usable Zope/Plone components, and for the sake of your own sanity, you should be developing your customisations and add-ons on the filesystem, as Zope products. Raphal Ritz' excellent MySite tutorial will give you a good and in-depth introduction to the topic.

Protecting your code

When creating classes which are intended to be accessed through the web (typically Archetypes content types or portal tools, though this applies to any Zope class derived from ExtensionClass) you must add security assertions on your methods. Much more information about this can be found in the Zope Developer Guide.

The following code example shows a general paradigm that is frequently followed in Archetypes products using the CMF core permissions. Please refer to the developer guide's chapter 6 for more details:

  from AccessControl import ClassSecurityInfo
  from Products.CMFCore import CMFCorePermissions
  # ... (additional imports and initialisation)

  class MyType(BaseContent):

    # ... (initialisation of schema and factory type info)

    # create a class security object to handle our security policy
    security = ClassSecurityInfo()

    # set a method to be publically accessible - all TTW code can
    # call this directly
    security.declarePublic('publicMethod')
    def publicMethod(self):
      # ... (docstring and method body)

    # set a method to be private - no TTW code can call this directly
    security.declarePrivate('privateMethod')
    def privateMethod(self):
      # ... (docstring and method body)

    # set a method to be protected by a given permission.
    # Only users with this permission in the context can call
    security.declareProtecte(CMFCorePermissions.View, 'protectedMethod')
    def protectedMethod(self):
      # ... (docstring and method body)

  # ... (type initialisation)

This rather amputated example shows how a class creates a ClassSecurityInfo object and uses it to declare its methods public (accessible to all through-the-web code), private (not accessible through the web) or protected by some permission - in this case the CMF core permission View. As with all matters of security, you should always protect your methods by the most limiting permission possible to ensure security is not breached.

Creating new workflows

Workflows can be created through the portal_workflow user interface. If you wish to ship such a workflow with your product, you must dump it to a python file and register it during Install.py. There is a dedicated product for this called DCWorkflowDump. When installed (just put it in your Products folder, no Plone installation necessary), it will give you a Dump tab when viewing a workflow in the ZMI to create a file containing the setup code for your workflow.

Typically, this workflow definition is dumped into your product's Extensions/ folder and called during Install.py to set up your workflow. If you subsequently wish to make changes to your workflow, you may wish to modify this dumped code directly rather than use the GUI and re-dump, as it is likely to be quicker. The dumped code should be fairly easy to understand once you know a bit about workflows.

An alternative way of creating workflow definitions is ArchGenXML. Using this tool, you can create UML state diagrams to represent your workflows. See the ArchGenXML documentation for details.

Finally, once your workflow has been created, you must register it with the workflow tool and associate any types you want with it (ArchGenXML does all of this automatically for you). The following code snippet is adapted from the PloneHelpCenter - the fine software that runs this documentation section - also found in the Collective. You may want to look at that product in more detail (a CVS checkout will be preferable) to see how workflows are used "in real life". In Extensions/Install.py, you may wish to put:

    # ...  (header and imports)

    def install(self):

        # ... (additional installation and setup)

        # Get our workflow and install it
        from Products.MyProduct.Extensions import MyWorkflow

        # The PloneHelpCenter does this, because it modifies the
        # dumped file to put the installation-initiating code inside
        # a method called install(). By default, it is called
        # automatically as soon as the workflow module is imported.

        # HCWorkflow.install()

        # Register the workflow with the tool 
        wf_tool = getToolByName(self, 'portal_workflow')

        # The id of the workflow if my_workflow, and the title is
        # My custom workflow. Due to a dumb API, these names have
        # to be entered verbatim in the argument to the method
        # below, with spaces and parentheses as shown.

        if not 'my_workflow' in wf_tool.objectIds():
            wf_tool.manage_addWorkflow('my_workflow (My custom workflow)',
                                       'my_workflow')

        # Do this after installing all workflows   
        wf_tool.updateRoleMappings()

        # Now tell our custom type MyType to use this workflow
        wf_tool.setChainForPortalTypes(pt_names=['MyType'], 
                                       chain='my_workflow')

        # ... (additional installation and setup)

That should be it - your custom workflow should be available for use after you install (or re-instal) your product. You are encouraged to take a look at the PloneHelpCenter code for a more comprehensive example.

 
by Martin Aspeli last modified December 9, 2005 - 23:22 All content is copyright Plone Foundation and the individual contributors.

Even easier in Plone 3!

Posted by Alex Clark at April 1, 2008 - 03:46
It is worth noting that it is no longer necessary (or possible) to create workflows with Python code (i.e. DCWorkflowDump) in Plone 3. You should use GenericSetup instead. e.g. Make some workflow changes TTW, then run the export step for the Workflow Tool, and add the generated XML code to your filesystem policy product (typically in profiles/default).

For any issues with the web site functionality, please file a ticket.

Please consult the policy on plone.org content if you want your content published on this site.

Servers and hosting by