Foswiki provides a flexible system of Access Control Lists that can be
used to control who can modify a topic. Sometimes this isn't quite
enough, and the access control depends on the state that a topic is
in.
For example,
- When writing documents compliant with ISO 9000 (e.g. a quality manual), it is essential that documents are approved by quality control
- In a defect tracking data base, defects typically transition through a series of states, from submission to resolution, with different actions available depending on the state of the defect.
- In a journal database, papers must be reviewed and approved by several experts in the field before being allowed to be published.
WorkflowPlugin lets you associate a state with a topic and then
control what other states that the topic can move to. You can define a
set of
states for controlled topics (e.g. "under revision", "waiting
for approval", "approved") and
transitions (e.g. "revise",
"approve") between these states. Furthermore, you can define which
users/groups are permitted to perform specific transitions, and
generate mail notifications whenever a topic state changes. You can
also generate reminders when a topic has been stuck-at a state for
longer than a certain time.
Usage
A topic is under document control if the preference variable
WORKFLOW
is set in the topic.
WORKFLOW
must be set to the wiki
name of a topic that describes your specific workflow (the _workflow
description topic_).
you can hide the setting in a normal view using HTML comments, or
better, you can put these settings into the local topic settings,
accessible from the "more..." screen. Or you can put the setting into
a formfield - see #FormBasedWorkflows below.
Settings in the workflow description topic
The workflow description topic must contain one state table and one
transition table. The state table describes the possible states a
document may be in (nodes in the flow diagram above), and the
transition table describes how documents move between states (arcs in
the flow diagram).
This is easiest illustrated using an example (available as
DocumentApprovalWorkflow /
ControlledDocument if the
plugin is installed).
Each row of the state table defines a state that a topic can be in:
| *State* | *Message* |
| UNDERREVISION | This document is being revised. |
| WAITINGFORQM | This document is waiting for approval by the Quality Manager. |
| WAITINGFORCTO | This document is waiting for approval by the CTO.|
| APPROVED | This document has been approved for release. |
Each row in the table defines a state where:
- the State column specifies a name for the state,
- the Message column defines a message which can be displayed on the document page when the document is in this state.
- optional Allow columns specify who is granted access to the topic when it moves to that state (see #AccessControl below)
The
State column must be first, but the other columns can appear in
any order. The first state in the table is the initial/default state.
The state table must be defined
before the transition table!
The transition table consists of four columns, as in this example:
| *State* | *Action* | *Next State* | *Form* | *Allowed* |
| UNDERREVISION | complete | WAITINGFORQM | | QualityGroup |
| WAITINGFORQM | approve | WAITINGFORCTO | QaForm | QualityManager |
| WAITINGFORQM | reject | UNDERREVISION | QaForm | QualityManager,QualityGroup |
| WAITINGFORCTO | approve | APPROVED | QaForm | TechnicalDirector |
| WAITINGFORCTO | reject | UNDERREVISION | QaForm | TechnicalDirector,QualityManager |
| APPROVED | revise | UNDERREVISION | PuForm | QualityGroup
|
Each row in this table defines a transition from one state to another state:
- the State column contains the name of a state from the state table,
- the Action column describes a possible action when the topic is in this state,
- the Next State column defines the new state of the document after the specified action has been performed,
- the Allowed column specifies who is allowed to perform the corresponding action,
- an optional Form column defines a form that is attached to the topic in this state.
- an optional Notify column specifies who should be notified when this transition fires. See Transition Notification below for more information.
In our example, anyone is allowed to revise the document when it is in
UNDERREVISION
state. After finishing the revision, the document can
be transitioned to the
WAITINGFORQM
state by any member of the
QualityGroup. It must then be approved by the QualityManager, and
after that by the TechnicalDirector. Even though they can't edit the
document themselves (see state table above), they
can reject the
revision and put the document back into the
UNDERREVISION
state. The
TechnicalDirector can transition the document to
APPROVED
state
where it rests until a member of the QualityGroup puts it under
revision again.
If a form name is given in the
Form column, this form will be
attached to the topic, and the topic will put in edit mode to allow
information to be provided in the form
when that state transition happens.
In the example above, a form of type ApprovedForm will
be attached to the topic when the CTO transitions the topic into
APPROVED
state.
- if there is already a form of a different type attached to the topic, then any fields that have the same name in the new form will be preserved.
- If no form is given, the existing form (if any) is left in place.
A typical usage of the form would be to collect additional information as the topic walks through the work flow, or to make information in the form unchangeable (by setting it to a
label
field) once a given state is reached.
Any
preference settings in the workflow
description topic that start with
WORKFLOW
are automatically available
when topics that use that workflow are viewed.
Transition Notification
If a
Notify column is given in the transition table, then that column
should contain a comma-separated list of notification targets to be emailed
when the transition is fired.
You can specify notification targets in any combination of the
following formats:
Format |
Example |
Email addresses |
webmaster@example.com |
User wiki names |
Main.WikiGuest |
Wiki group names |
Main.AdminGroup |
Last user-in-state |
LASTUSER_APPROVED |
Notify column entries can contain macros, which are expanded in the
context of the topic
after the transition has happened.
Last user-in-state expands to the name of the user who last transitioned
to the given state.
By default, notification emails are formatted according to the
mailworkflowtransition
skin template. You can override
this by providing a template topic called
WorkflowTransitionMailTemplate
in the web where the transitioning topic resides.
In addition you can define custom email templates in the
Notify
column, using the syntax
template(Web.MyTopic)
. This allows you to
do more sophisticated email notification, for example you could write
a different custom email template for each transition.
For example, the
Notify column in the transition table below will email
jim@example.com
using the default template, and expand both the
EmailOne
and
EmailTwo
templates, sending the results to whatever email addresses are defined on their respective
To
,
Cc
, or
Bcc
lines:
| *State* | .... | *Notify* |
| PENDING | .... | jim@example.com, template(EmailOne), template(EmailTwo) |
Custom templates have the additional macro:
TEMPLATE |
web.topic name of the template |
Note: you can also re-notify a transition when the topic has been stuck for
a certain length of time in a state. This is done using the
tools/workflowremind
script. This script is normally run from a cron job, and can be run without parameters to see how it works.
the
WORKFLOWDEFAULTEMAILTEMPLATE
preference is no longer supported. Please use local template topics and/or skin templates instead.
Settings in your controlled document/topic
As described above the topic needs to contain a definition for the variable
WORKFLOW
for it to be controlled under the approval workflow. This is best set as a document-specific preference setting in the
More topic actions
screen.
WORKFLOW* -- macros associated with WorkflowPlugin
All the following macros accept web and topic parameters:
Parameter |
Meaning |
Default |
web |
(Optional) name of the web containing the topic |
current web |
topic |
(Optional) name of the topic (may use web.topic syntax) |
current topic |
Where it makes sense, the macros also accept a
rev
parameter.
If the topic is
not controlled, then any references to
WORKFLOW
macros are simply removed. You can use this behaviour to place these
tags in the header or footer in your skin templates. They appear only
if the currently displayed topic is controlled.
%WORKATTACHTOPIC%
Expands to a link that lets you attach to the topic (if you are not
able to modify the topic, either in the workflow sense or according to the
tandard access controls, the link will be
struck out).
%WORKFLOWEDITTOPIC%
Expands to a link that lets you edit the topic (if you are not able to
modify the topic, either in the workflow sense or according to the
standard access controls, the link will be
struck
out).|
%WORKFLOWFORK{...}%
Expands to a button that will create one or more copies of a topic
(which must be in a workflow). You must have edit (CHANGE) access to
the topic to be forked.
Parameter |
Meaning |
Default |
newnames="NameOne,NameTwo,..." |
Comma-separated list of name(s) of the new topic(s) to create. AUTOINC is supported, and you can use a web specifier on the topic names. |
required, no default. |
label="Fork" |
Label to use in the button |
"Fork" |
lockdown="on" |
Set this if you want the forked topic to be set as uneditable by all except admins after the fork. This will also prevent the topic from being forked again. |
off |
Used when you have a topic that has to be split to follow different
routes through a workflow - for example, when a requirement is refined
to create two new requirements that must follow their own lifecycles;
or perhaps a problem report is found to affect two different
components of a system, and the resolutions have to be separately
tracked.
For example,
%WORKFLOWFORK{topic="OriginalTopic" label="Divide and conquer" newnames="ForkPathOne,ForkPathTwo" lockdown="on"}%
will create two copies of
OriginalTopic
, named
ForkPathOne
and
ForkPathTwo
and set the
OriginalTopic
as uneditable (using
ALLOWTOPICCHANGE).
The fork copies do not inherit the history of the forked topic - their
history starts afresh with the fork.
due to a bug in versions of the plugin prior to Oct 2009, the
default parameter was interpreted as the name of the
new topic to fork to. This has been corrected, but the macro will
revert to the old meaning if you omit the
newnames
parameter.
%WORKFLOWTRANSITION%
Expands to either (a) a pull-down menu if the user can perform more
than one transition, (b) a button if the current user can only perform
one transition, or (c) empty space if the current user is not allowed
to perform any action. You can change the format of the button using a
CSS class (see WORKFLOWTRANSITIONCSSCLASS below) or by deriving your own
version of
workflowstrings.tmpl
%WORKFLOWHISTORY{...}%
Expands to the history of state transitions the topic has undergone.
Parameter |
Meaning |
Default |
format |
Format of each transition |
$state -- $date |
header |
Header before results |
|
footer |
Footer after results |
|
separator |
Separator between results |
<br /> |
include |
Perl regular expression matching states to include |
|
exclude |
Perl regular expression matching states to exclude |
|
The
format
,
header
,
footer
and
separator
parameters provide the control necessary to make the history look nice
when it is viewed.
In this example the history is formatted as a simple table:
%WORKFLOWHISTORY{format="| $state | $author | $date |" separator="$n"}%
The standard
format tokens are supported, as well as the following
special tokens:
Token |
Expands to |
$author |
Who triggered the transition to this state (also $user and $wikiusername ) |
$comment |
Comment accompanying the record |
$date |
Date/time of the transition in the default format (you can format your own date using the same formatting tokens as used by %GMTIME% ) |
$index |
1-based number of this result |
$name |
Version at the transition (also $rev ) |
$state |
The state of the topic after the recorded event occurred |
%WORKFLOWLAST{...}%
Expands to the history recorded when the topic was last in a certain state.
The
format
is the same as that used for
%WORKFLOWHISTORY%
.
%WORKFLOWSTATE%
Expands to the current state of the topic.
%WORKFLOWSTATEMESSAGE%
Expands to the corresponding message in the state table for the current state.
If you replace
%EDITTOPIC%
with
%WORKFLOWEDITTOPIC%
in your skin templates, then the
Edit link is crossed out when the user is not allowed to edit the page in a state.
Similarly, you can use
%WORKFLOWATTACHTOPIC%
in your skin templates to cross out the
Attach link.
Content-sensitive workflows
Advanced Flows can be made sensitive to the content of the controlled
topics. The
Allow columns in the state table, and the
Next State
and
Allowed columns in the transition table, support the use of macros
which are expanded when the topic is viewed. For example, you can use the
META
macro to pick up values for these fields from the form
attached to the viewed topic:
State table
| *State* | *Allow CHANGE* | *Message* |
| WAITINGFORAPPROVAL | %META{"formfield" name="MayModify"}% | This document is waiting for approval |
Transition Table
| *State* | *Action* | *Next State* | *Allowed* |
| WAITINGFORAPPROVAL | approve | %META{"formfield" name="ApprovedState"}% | %META{"formfield" name="MayApprove"}% |
See #AccessControl for more information.
You can also define other macros starting with
WORKFLOW
in the workflow
description topic. These will be expanded to their defined values in any
topic that uses the workflow. For example:
- Set WORKFLOWNOTICE = This topic is under document control.
will define
WORKFLOWNOTICE
in any topic that uses the workflow.
Reporting
A common requirement is to report on the status of topics that are in different states in the workflow. You can use the query search to search for topics in a specific state. For example, to search for all topics in state "APPROVED":
%SEARCH{"META:WORKFLOW.name='APPROVED'" type="query"}%
Access Control
The plugin uses extended Foswiki permissions to manage access to topics.
In the state table, you can have any number of 'Allow' columns, for example
'Allow CHANGE' or 'Allow VIEW'. These columns dictate the Foswiki permissions
that are applied when a topic is transitioned to that state by the plugin. For
example, if the state table contains:
| *State* | *Allow CHANGE* | *Allow VIEW* |
| UNDERREVISION | EngineeringGroup | |
When a topic is transitioned to this state, all other topic-level permissions
will automatically be removed, and the permissions:
will be added to the topic.
Similarly the 'Allowed' column in the transition table controls who is allowed to perform that transition.
Normally entries in 'Allow' columns are user (or group) names, such as
WikiGuest. However:
- Empty 'Allow*' columns are taken as meaning no restriction.
- The special entry
nobody
can be used to restrict access for everyone (except admins).
- You can exclude a specific user (or group) from access using
not(WikiGuest)
.
- You can explicitly exclude the user who last transitioned the topic to a specific state using
not(LASTUSER_{State})
.
- You can use Foswiki macros. These will be expanded in the context of the controlled topic.
For historical reasons,
Allow Edit is mapped to
Allow CHANGE.
Only ALLOWTOPIC access controls in metadata preference settings
are managed; access controls explicit in the text (set by * Set) are
not managed, nor are
DENYTOPIC
preferences in metadata. Access
controls set in these ways may prevent the plugin from working
correctly.
Stuck-At Reminders
You may want to be able to issue a notification is a topic is stuck in a state for longer than a given time, to keep the workflow moving. For this the plugin provides the
tools/workflowremind
perl script, which is run on the server - either manually, or using a
cron
job. To find out how this is used, change to the
tools
directory on the server and
perl workflowremind
with no parameters.
The mail sent by this script is formatted using
skin template called
mailworkflowremind
. You can override this by providing a template topic called
WorkflowRemindMailTemplate
in the web where the transitioned topic resides.
The following identifiers are expanded in the template:
EMAILTO |
Comma-separated list of email addressess |
TRANSITION |
Name of the transition |
TARGET_STATE |
State being transitioned to |
STUCK |
How long the topic has been stuck in that state |
Normally the workflow for a topic is defined in a Foswiki preference setting. You can also use a form field for this.
If there is no WORKFLOW preference setting, then the form field "Workflow"
is used for the workflow name. Note that because the form can change when
a transition happens, the so can the workflow. Using this technique,
it is possible for a topic to switch between workflows as the result of a
transition.
Controlling Appearance
The appearance of all buttons and special screens is controlled through the use of
skin templates:
-
workflowstrings.tmpl
- contains translateable definitions for all error messages and inline controls,
-
mailworkflowtransition.tmpl
is the template for the email sent for a transition * mailworkflowmither.tmpl
is the template used when re-mailing a transition notification, * workflowedit.tmpl
is the template used for editing during a transition (i.e. when a new form is attached)
For simple customisation of the default templates, the
preference
WORKFLOWTRANSITIONCSSCLASS
can be set to the names of one or more CSS
classes that are used to style buttons, such as the transition and fork buttons.
More complex customisations can be achieved through use of skins - see
SkinTemplates for more information.
The plugin uses custom meta-data to contol and track workflows. Most users
will never need to know about this; the following is for experts who want
to understand the format of that metadata.
-
name
- current state of this topic
-
LAST(TIME|USER|VERSION|COMMENT)
- deprecated, replaced with WORKFLOWHISTORY
META:WORKFLOWHISTORY
- may be many
All workflow history entries have the following fields:
-
name
- revision identifier
-
author
- who did the transition/fork
-
date
- time the transition/fork happened (epoch secs)
State transitions are recorded as follows:
-
state
- state transitioned into
-
comment
- comment accompanying the transition
Forks are recorded in both the forked topic, and the topic created by the fork.
In the topic that was forked from,
-
forkto
- comma-separated list of web.topic generted by the fork
In each topic that is forked to,
-
forkfrom
- web.topic that the topic is forked from
-
rev
- the revision of the forkfrom
topic after the fork was done
Debugging Workflows
Developing complex workflows is quite straightforward, though from time-to-time
you may require some additional debugging support. In this case you can enable
the
WORKFLOWDEBUG
preference, either in the workflow description topic or in
an individual controlled topic, to get extra information about the macros
being expanded when a controlled topic is viewed. Information is embedded
into the topic in HTML comments (use 'view source' in the browser to see them)
and, if
{Plugins}{WorkflowPlugin}{Debug}
is enabled in configure, additional
messages (mostly related to access control) are written to the debug log (requires administrator access).
History and Acknowledgements
This plugin was motivated by
Thomas
Weigert's
WorkFlowAddOn and
its first version (then called ApprovalPlugin) was written by Thomas
Hartkens, albeit it was focused on document approval and
control.
Thomas Weigert then merged
the functionality of the
WorkFlowAddOn into this
plugin. Finally the plugin was almost completely rewritten to the
reverse-engineered spec (a few of the crappy bits were dropped) by
Crawford Currie, for maintainability
and efficiency.
Installation Instructions
This version of the plugin is intended for use with Foswiki 2.0 and later.
If you are running an older Foswiki, do not install it!
You do not need to install anything in the browser to use this extension. The following instructions are for the administrator who installs the extension on the server.
Open configure, and open the "Extensions" section. "Extensions Operation and Maintenance" Tab -> "Install, Update or Remove extensions" Tab. Click the "Search for Extensions" button.
Enter part of the extension name or description and press search. Select the desired extension(s) and click install. If an extension is already installed, it will
not show up in the
search results.
You can also install from the shell by running the extension installer as the web server user: (Be sure to run as the webserver user, not as root!)
cd /path/to/foswiki
perl tools/extension_installer <NameOfExtension> install
If you have any problems, or if the extension isn't available in
configure
, then you can still install manually from the command-line. See
https://foswiki.org/Support/ManuallyInstallingExtensions for more help.
Note: The script
convert.pl.txt
will convert topics written for the ApprovalPlugin to the WorkflowPlugin. The script takes a topic at the standard input and outputs the converted topic on standard output. Rename the file from
convert.pl.txt
to
convert.pl
.
Look at the examples in the Sandbox web.
Note: For strict access control, the plugin should know who is looking at the controlled document/topic at all times. To enable this, you may want to set up the wiki in such way that users have to log-in
even if they just display a topic.
Upgrade note If you are upgrading from a version before 10 Nov 2008 please note that the format of the WORKFLOWHISTORYFORMAT preference has changed slightly, in that:
- enclosing double quotes are no longer removed from the value. This changes has been to bring this preference definition into line with other preference definitions.
-
$n
is interpreted as \n, not <br>, in line with the standard format tokens. If you want a <br> in the format string, then enter it as <br> or $percntBR$percnt.