Metadata-Version: 1.0
Name: ftw.lawgiver
Version: 1.0
Summary: Generate your Plone workflows by describing it in plain text with a DSL.
Home-page: https://github.com/4teamwork/ftw.lawgiver
Author: 4teamwork GmbH
Author-email: mailto:info@4teamwork.ch
License: GPL2
Description: ftw.lawgiver
        ============
        
        ``ftw.lawgiver`` generates Plone workflows based on a human readable
        specification written in a custom
        `DSL <http://en.wikipedia.org/wiki/Domain-specific_language>`_.
        
        .. contents:: Table of Contents
        
        
        Motivation
        ----------
        
        Developing and maintaining complex Plone workflows is a time-consuming and
        cumbersome endeavor. Dozens of permissions need to be managed for different
        roles and different workflow states. Usually, this has to be done directly in
        the ZMI of Zope by selecting or unselecting thousands of checkboxes. This
        process has been shown to be very tedious and prone to errors. Furthermore, it
        is no simple task to document the workflow and the associated design decisions
        which led to the resulting configuration of permissions and roles. The extension
        or adaption of an existing workflow becomes very difficult, leading to workflows
        which are barely maintainable.
        
        Another problem poses the communication between workflow integrator and
        customer. The security system of Zope is based on a role-based access control
        (RBAC) which is intrinsically complex due to its use of roles, permissions, and
        workflow states. Experience has shown that these security concepts can be hard
        to convey to customers.
        
        
        How it works
        ------------
        
        ``ftw.lawgiver`` helps solving these problems by using a DSL to describe how
        a workflow should work. The lawgiver then generates the complete workflow
        definition (``definition.xml``) based on this specification.  By separating this
        specification from the resulting workflow definition (which is in XML) the
        specification does not have to use permissions--handling the permissions is the
        job of the lawgiver.
        
        Using the specification file the workflow can easily be regenerated at any time
        and will handle additional permissions automatically when regenerated. However,
        it is still the task of the developer to regenerate the ``definition.xml`` when
        more or other permissions have to be managed. He or she have to make sure that
        the workflow is properly installed with an upgrade step / reindexing security.
        
        
        Installation
        ------------
        
        - Add ``ftw.lawgiver`` to your buildout configuration:
        
        .. code:: rst
        
            [instance]
            eggs +=
                ftw.lawgiver
        
        - Install the generic setup profile of ``ftw.lawgiver``.
        
        
        Compatibility
        -------------
        
        Runs with `Plone <http://www.plone.org/>`_ `4.3`.
        
        
        Action groups
        -------------
        
        In the specification we use the concept of so called action groups for
        describing what a role is allowed to do. It basically groups together a bunch of
        semantically similar Plone / Zope permissions so that we only have to define the
        workflow based on these action groups and not on individual permissions.
        
        For example there is an ``Access`` action group which contains permissions such
        as ``View`` and ``Access Contents Information``.
        
        
        Registering permissions to an action group
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        
        The registration of a permission to an action group should be done in the
        package where the permission is defined.  This allows to keep changes of the
        permissions and action group registrations together in branches, for reviews
        etc. ``ftw.lawgiver`` already assigns default Plone / Zope permissions to action
        groups.
        
        The registration is done in ZCML.
        Here is an example ``lawgiver.zcml``:
        
        .. code:: xml
        
            <configure
                xmlns="http://namespaces.zope.org/zope"
                xmlns:lawgiver="http://namespaces.zope.org/lawgiver"
                i18n_domain="my.package">
        
                <include package="ftw.lawgiver" file="meta.zcml" />
        
                <lawgiver:map_permissions
                    action_group="add content"
                    permissions="my.package: Add Foo,
                                 my.package: Add Bar"
                    />
        
            </configure>
        
        If you define multiple permissions in the same `map_permissions` directive
        make sure to separate them by comma.
        
        By putting the ZCML in a separate ``lawgiver.zcml`` file you can define
        lawgiver in your addon package without having to define a dependency to
        ``ftw.lawgiver`` by using ``zcml:condition`` while loading it in your default
        ``configure.zcml``:
        
        .. code:: xml
        
            <configure
                xmlns="http://namespaces.zope.org/zope"
                xmlns:zcml="http://namespaces.zope.org/zcml"
                i18n_domain="my.package">
        
                <include zcml:condition="installed ftw.lawgiver" file="lawgiver.zcml" />
        
            </configure>
        
        
        Overriding action groups
        ~~~~~~~~~~~~~~~~~~~~~~~~
        
        Maybe the permission to action group mapping does not work well for a specific
        workflow and you would like to change to mapping for this workflow only.
        
        This can be easily achieved by also defining the workflow in the ZCML:
        
        .. code:: xml
        
            <configure
                xmlns="http://namespaces.zope.org/zope"
                xmlns:lawgiver="http://namespaces.zope.org/lawgiver"
                i18n_domain="my.package">
        
                <include package="ftw.lawgiver" file="meta.zcml" />
        
                <lawgiver:map_permissions
                    action_group="add content"
                    permissions="my.package: Add Foo,
                                 my.package: Add Bar"
                    workflow="my_workflow"
                    />
        
            </configure>
        
        
        The workflow specification
        --------------------------
        
        The specification is written in a plain text file (``specification.txt``) in
        the same directory where the ``definition.xml`` is saved.
        
        
        States and transitions
        ~~~~~~~~~~~~~~~~~~~~~~
        
        The states and transitions are defined in simple lists:
        
        .. code:: rst
        
            [My Custom Workflow]
            Description: A three state publication workflow
            Initial Status: Private
        
            Status Private:
        
            Status Pending:
        
            Status Published:
        
            Transitions:
              Publish (Private => Published)
              Submit for publication (Private => Pending)
              Reject (Pending => Private)
              Retract (Pending => Private)
              Publish (Pending => Published)
              Reject (Published => Private)
        
        The asterisk (`*`) in the state list indicates that this state is the initial
        state.  We are not using any internal ids for workflow states or
        transitions. Instead, we use the same labels which the user will actually
        see--the ids are automatically generated by ``ftw.lawgiver``.
        
        
        Role mapping
        ~~~~~~~~~~~~
        
        In Plone we have a given set of rather technical roles (e.g. Editor,
        Contributor, Reader) which may not apply for all use cases in real life. The
        customer may have own roles with different names.  Since the existing roles are
        already well established in Plone it is usually not a good thing to add new
        roles to Plone. It is better to try to reuse the existing roles.
        
        Because the customer has different labels for his roles we need to map
        customer roles to Plone roles:
        
        .. code:: rst
        
            Role mapping:
              editor-in-chief => Reviewer
              editor => Editor
              everyone => Anonymous
        
        In our example we have only "normal" editors and an "editor-in-chief" who can
        review and publish the contents.  We do not have to use the Contributor role
        since our editors can edit, add new content, and request a review for existing
        content. Therefore, it is not necessary to distinguish Editor and Contributor
        role.
        
        
        General statements
        ~~~~~~~~~~~~~~~~~~
        
        Usually there are some general statements, for example that a user with
        adminstrator role can always edit the contents on any workflow state.  Such
        statements should not be repeated for every state but defined once as a general
        statement.
        
        An example:
        
        .. code:: rst
        
            General:
              An administrator can always view the content
              An administrator can always edit the content
              An administrator can always delete the content
        
        These general statements apply for all states.
        
        
        Describing states
        ~~~~~~~~~~~~~~~~~
        
        For each state we describe the actions a user with a certain role can do.  We
        have the principle that any user / role is NOT allowed do anything by default,
        we have to explicitly list every action he will be allowed to perform.
        
        .. code:: rst
        
            Status Private:
              An editor can view this content.
              An editor can edit this content.
              An editor can delete this content.
              An editor can add new content.
              An editor can submit for publication.
              An editor-in-chief can view this content.
              An editor-in-chief can edit this content.
              An editor-in-chief can delete this content.
              An editor-in-chief can add new content.
              An editor-in-chief can publish this content.
        
            Status Pending:
              An editor can view this content.
              An editor can add new content.
              An editor can retract this content.
              An editor-in-chief can view this content.
              An editor-in-chief can edit this content.
              An editor-in-chief can delete this content.
              An editor-in-chief can add new content.
              An editor-in-chief can publish this content.
              An editor-in-chief can reject this content.
        
            Status Published:
              An editor can view this content.
              An editor can add new content.
              An editor can retract this content.
              An editor-in-chief can view this content.
              An editor-in-chief can add new content.
              An editor-in-chief can retract this content.
              Anyone can view this content.
        
        
        Role inheritance
        ~~~~~~~~~~~~~~~~
        
        Roles can be inherited from other roles, globally and for a single status:
        
        .. code:: rst
        
            [Role Inheritance Workflow]
            Initial Status: Foo
        
            Role mapping:
              editor => Editor
              editor-in-chief => Reviewer
              administrator => Site Administrator
        
            General:
              An administrator can always perform the same actions as an editor.
              An administrator can always perform the same actions as an editor-in-chief.
        
            Status Foo:
              An editor-in-chief can perform the same actions as an editor.
              An editor can view this content.
              An editor can edit this content.
        
            Status Bar:
              An editor can view this content.
              An editor-in-chief can view this content.
              An editor-in-chief can edit this content.
        
        
        Worklists
        ~~~~~~~~~
        
        Worklists are automatically generated for you when you grant access to the
        worklist:
        
        .. code:: rst
        
            [A workflow]
            ...
        
            Status Pending:
              An editor-in-chief can access the worklist.
        
        Those "can access the worklist" statements do not work in the "General" section,
        they need to be defined a "Status" section.
        
        For each status with "can access the worklist" statements a worklist is
        generated, guarded with the role for which there is a statement.
        
        
        Workflow specification discovery
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        
        All workflow directories in registered generic setup profiles
        are automatically scanned for workflow specifications.
        Just place a ``specification.txt`` in a workflow directory and ``ftw.lawgiver``
        will discover it automatically.
        
        Example paths:
        
        - Specification: ``profiles/default/workflows/my_custom_workflow/specification.txt``
        - Workflow XML: ``profiles/default/workflows/my_custom_workflow/definition.txt``
        
        In this example it is assumed that ``profiles/default`` is a registered generic setup
        profile directory.
        
        
        Changing Transition URLs
        ~~~~~~~~~~~~~~~~~~~~~~~~
        
        Sometimes the transition URLs need to point to another view.  This can be
        achieved by using the `transition-url` option, where a string can be passed
        which will then be substituted with the `transition` id.  Be sure to use a
        double `%%` for parts which should not be replaced when generating the workflow,
        such as the `%%(content_url)s`.
        
        Example:
        
        .. code:: rst
        
            transition-url = %%(content_url)s/custom_wf_action?workflow_action=%(transition)s
        
        
        Generating the workflow
        -----------------------
        
        For generating the workflow go to the lawgiver control panel (in the Plone
        control panel). There you can see a list of all workflows and by selecting one
        you can see the specification and other details, such as the action groups.
        
        On this view you can generate the workflow (automatically saved in the
        ``definition.xml`` in the same directory as the ``specification.txt``) and you
        can install the workflow / update the security.
        
        .. image:: https://raw.github.com/4teamwork/ftw.lawgiver/master/docs/screenshot-workflow-details.png
        
        
        Testing the workflow
        --------------------
        
        It is important to detect when you have to rebuild your workflow.
        It is also important to dected permissions from third party addons which
        are not yet mapped to action groups.
        
        By subclassing the `WorkflowTest` it is easy to write a test for your
        workflow:
        
        .. code:: python
        
            from ftw.lawgiver.tests.base import WorkflowTest
            from my.package.testing import MY_INTEGRATION_TESTING
        
        
            class TestMyWorkflow(WorkflowTest):
        
                # The workflow path may be a path relative to the this file or
                # an absolute path.
                workflow_path = '../profiles/default/workflows/my-workflow'
        
                # Use an integration testing layer.
                layer = MY_INTEGRATION_TESTING
        
        What is tested?
        
        - The test will fail when your workflow (`definition.xml`) needs to be
          regenerated. This may be because new permissions should be managed.
        
        - The test will faile when you install new addons which provide new
          permisisons. The permissions should be mapped to action groups or marked
          as unmanaged explicitly:
        
        .. code:: xml
        
            <configure
                xmlns="http://namespaces.zope.org/zope"
                xmlns:lawgiver="http://namespaces.zope.org/lawgiver"
                i18n_domain="ftw.lawgiver">
        
                <include package="ftw.lawgiver" file="meta.zcml" />
        
        
                <lawgiver:ignore
                    workflow="my_workflow"
                    permissions="ATContentTypes: Upload via url,
                                 ATContentTypes: View history"
                    />
        
            </configure>
        
        
        Specialities
        ------------
        
        Deleting content
        ~~~~~~~~~~~~~~~~
        
        The ``ftw.lawgiver`` uses `collective.deletepermission`_.  If you generate a
        workflow using lawgiver and install it in production without lawgiver, be sure
        to install `collective.deletepermission`_!
        
        `collective.deletepermission`_ solves a delete problem which occurs in certain
        situations by adding a new delete permission. See its readme for further
        details.
        
        For beeing able to delete a content, the user should have the "delete" action
        group (`Delete portal content`) on the content but also "add" (`Delete objects`)
        on the parent content
        
        
        Example
        -------
        
        In our tests we have an up to date
        `example specification.txt <https://github.com/4teamwork/ftw.lawgiver/blob/master/ftw/lawgiver/tests/profiles/custom-workflow/workflows/my_custom_workflow/specification.txt>`_, from which the
        `definition.xml <https://github.com/4teamwork/ftw.lawgiver/blob/master/ftw/lawgiver/tests/profiles/custom-workflow/workflows/my_custom_workflow/definition.xml>`_
        is generated.
        
        
        Links
        -----
        
        - Main github project repository: https://github.com/4teamwork/ftw.lawgiver
        - Issue tracker: https://github.com/4teamwork/ftw.lawgiver/issues
        - Package on pypi: http://pypi.python.org/pypi/ftw.lawgiver
        - Continuous integration: https://jenkins.4teamwork.ch/search?q=ftw.lawgiver
        
        
        Copyright
        ---------
        
        This package is copyright by `4teamwork <http://www.4teamwork.ch/>`_.
        
        ``ftw.lawgiver`` is licensed under GNU General Public License, version 2.
        
        .. _collective.deletepermission: https://github.com/4teamwork/collective.deletepermission
        
        .. image:: https://cruel-carlota.pagodabox.com/ef218e7bdb19163396b77d70f31e984e
           :alt: githalytics.com
           :target: http://githalytics.com/4teamwork/ftw.lawgiver
        
        Changelog
        =========
        
        
        1.0 (2013-05-28)
        ----------------
        
        - Initial implementation.
          [jone]
        
Keywords: ftw lawgiver generate workflows dsl
Platform: UNKNOWN
Classifier: Framework :: Plone
Classifier: Framework :: Plone :: 4.3
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development :: Libraries :: Python Modules
