Remove (external) workflows app which has been obsolete since the move to the new schema
- Legacy-Id: 6299
This commit is contained in:
parent
e5871284b6
commit
f7ad84ecb9
|
@ -154,7 +154,6 @@ INSTALLED_APPS = (
|
|||
'django.contrib.humanize',
|
||||
'django.contrib.messages',
|
||||
'south',
|
||||
'workflows',
|
||||
'permissions',
|
||||
'ietf.person',
|
||||
'ietf.name',
|
||||
|
|
1
workflows/.gitignore
vendored
1
workflows/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/*.pyc
|
|
@ -1,61 +0,0 @@
|
|||
# workflows imports
|
||||
import workflows.utils
|
||||
|
||||
class WorkflowBase(object):
|
||||
"""Mixin class to make objects workflow aware.
|
||||
"""
|
||||
def get_workflow(self):
|
||||
"""Returns the current workflow of the object.
|
||||
"""
|
||||
return workflows.utils.get_workflow(self)
|
||||
|
||||
def remove_workflow(self):
|
||||
"""Removes the workflow from the object. After this function has been
|
||||
called the object has no *own* workflow anymore (it might have one via
|
||||
its content type).
|
||||
|
||||
"""
|
||||
return workflows.utils.remove_workflow_from_object(self)
|
||||
|
||||
def set_workflow(self, workflow):
|
||||
"""Sets the passed workflow to the object. This will set the local
|
||||
workflow for the object.
|
||||
|
||||
If the object has already the given workflow nothing happens.
|
||||
Otherwise the object gets the passed workflow and the state is set to
|
||||
the workflow's initial state.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
workflow
|
||||
The workflow which should be set to the object. Can be a Workflow
|
||||
instance or a string with the workflow name.
|
||||
obj
|
||||
The object which gets the passed workflow.
|
||||
"""
|
||||
return workflows.utils.set_workflow_for_object(workflow)
|
||||
|
||||
def get_state(self):
|
||||
"""Returns the current workflow state of the object.
|
||||
"""
|
||||
return workflows.utils.get_state(self)
|
||||
|
||||
def set_state(self, state):
|
||||
"""Sets the workflow state of the object.
|
||||
"""
|
||||
return workflows.utils.set_state(self, state)
|
||||
|
||||
def set_initial_state(self):
|
||||
"""Sets the initial state of the current workflow to the object.
|
||||
"""
|
||||
return self.set_state(self.get_workflow().initial_state)
|
||||
|
||||
def get_allowed_transitions(self, user):
|
||||
"""Returns allowed transitions for the current state.
|
||||
"""
|
||||
return workflows.utils.get_allowed_transitions(self, user)
|
||||
|
||||
def do_transition(self, transition, user):
|
||||
"""Processes the passed transition (if allowed).
|
||||
"""
|
||||
return workflows.utils.do_transition(self, transition, user)
|
Binary file not shown.
|
@ -1,60 +0,0 @@
|
|||
# German translations for django-workflows
|
||||
# Copyright (C) 2010 Kai Diefenbach
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# Kai Diefenbach <kai.diefenbach@iqpp.de>, 2010.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: 1.0\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2010-04-02 09:16+0200\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: models.py:98 models.py:199 models.py:237
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: models.py:200 models.py:238 models.py:285 models.py:307
|
||||
msgid "Workflow"
|
||||
msgstr "Arbeitsablauf"
|
||||
|
||||
#: models.py:201
|
||||
msgid "Transitions"
|
||||
msgstr "Übergänge"
|
||||
|
||||
#: models.py:239
|
||||
msgid "Destination"
|
||||
msgstr "Ziel"
|
||||
|
||||
#: models.py:240
|
||||
msgid "Condition"
|
||||
msgstr "Kondition"
|
||||
|
||||
#: models.py:241 models.py:350 models.py:373
|
||||
msgid "Permission"
|
||||
msgstr "Recht"
|
||||
|
||||
#: models.py:258 models.py:282
|
||||
msgid "Content type"
|
||||
msgstr "Inhaltstyp"
|
||||
|
||||
#: models.py:259 models.py:283
|
||||
msgid "Content id"
|
||||
msgstr "Inhalts-ID"
|
||||
|
||||
#: models.py:261 models.py:349 models.py:372
|
||||
msgid "State"
|
||||
msgstr "Status"
|
||||
|
||||
#: models.py:306
|
||||
msgid "Content Type"
|
||||
msgstr "Inhaltstyp"
|
||||
|
||||
#: models.py:374
|
||||
msgid "Role"
|
||||
msgstr "Rolle"
|
1
workflows/migrations/.gitignore
vendored
1
workflows/migrations/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/*.pyc
|
|
@ -1,225 +0,0 @@
|
|||
|
||||
from south.db import db
|
||||
from django.db import models
|
||||
from workflows.models import *
|
||||
|
||||
class Migration:
|
||||
|
||||
def forwards(self, orm):
|
||||
|
||||
# Adding model 'Workflow'
|
||||
db.create_table('workflows_workflow', (
|
||||
('id', orm['workflows.Workflow:id']),
|
||||
('name', orm['workflows.Workflow:name']),
|
||||
('initial_state', orm['workflows.Workflow:initial_state']),
|
||||
))
|
||||
db.send_create_signal('workflows', ['Workflow'])
|
||||
|
||||
# Adding model 'StatePermissionRelation'
|
||||
db.create_table('workflows_statepermissionrelation', (
|
||||
('id', orm['workflows.StatePermissionRelation:id']),
|
||||
('state', orm['workflows.StatePermissionRelation:state']),
|
||||
('permission', orm['workflows.StatePermissionRelation:permission']),
|
||||
('role', orm['workflows.StatePermissionRelation:role']),
|
||||
))
|
||||
db.send_create_signal('workflows', ['StatePermissionRelation'])
|
||||
|
||||
# Adding model 'StateInheritanceBlock'
|
||||
db.create_table('workflows_stateinheritanceblock', (
|
||||
('id', orm['workflows.StateInheritanceBlock:id']),
|
||||
('state', orm['workflows.StateInheritanceBlock:state']),
|
||||
('permission', orm['workflows.StateInheritanceBlock:permission']),
|
||||
))
|
||||
db.send_create_signal('workflows', ['StateInheritanceBlock'])
|
||||
|
||||
# Adding model 'WorkflowModelRelation'
|
||||
db.create_table('workflows_workflowmodelrelation', (
|
||||
('id', orm['workflows.WorkflowModelRelation:id']),
|
||||
('content_type', orm['workflows.WorkflowModelRelation:content_type']),
|
||||
('workflow', orm['workflows.WorkflowModelRelation:workflow']),
|
||||
))
|
||||
db.send_create_signal('workflows', ['WorkflowModelRelation'])
|
||||
|
||||
# Adding model 'WorkflowPermissionRelation'
|
||||
db.create_table('workflows_workflowpermissionrelation', (
|
||||
('id', orm['workflows.WorkflowPermissionRelation:id']),
|
||||
('workflow', orm['workflows.WorkflowPermissionRelation:workflow']),
|
||||
('permission', orm['workflows.WorkflowPermissionRelation:permission']),
|
||||
))
|
||||
db.send_create_signal('workflows', ['WorkflowPermissionRelation'])
|
||||
|
||||
# Adding model 'State'
|
||||
db.create_table('workflows_state', (
|
||||
('id', orm['workflows.State:id']),
|
||||
('name', orm['workflows.State:name']),
|
||||
('workflow', orm['workflows.State:workflow']),
|
||||
))
|
||||
db.send_create_signal('workflows', ['State'])
|
||||
|
||||
# Adding model 'Transition'
|
||||
db.create_table('workflows_transition', (
|
||||
('id', orm['workflows.Transition:id']),
|
||||
('name', orm['workflows.Transition:name']),
|
||||
('workflow', orm['workflows.Transition:workflow']),
|
||||
('destination', orm['workflows.Transition:destination']),
|
||||
('condition', orm['workflows.Transition:condition']),
|
||||
('permission', orm['workflows.Transition:permission']),
|
||||
))
|
||||
db.send_create_signal('workflows', ['Transition'])
|
||||
|
||||
# Adding model 'WorkflowObjectRelation'
|
||||
db.create_table('workflows_workflowobjectrelation', (
|
||||
('id', orm['workflows.WorkflowObjectRelation:id']),
|
||||
('content_type', orm['workflows.WorkflowObjectRelation:content_type']),
|
||||
('content_id', orm['workflows.WorkflowObjectRelation:content_id']),
|
||||
('workflow', orm['workflows.WorkflowObjectRelation:workflow']),
|
||||
))
|
||||
db.send_create_signal('workflows', ['WorkflowObjectRelation'])
|
||||
|
||||
# Adding model 'StateObjectRelation'
|
||||
db.create_table('workflows_stateobjectrelation', (
|
||||
('id', orm['workflows.StateObjectRelation:id']),
|
||||
('content_type', orm['workflows.StateObjectRelation:content_type']),
|
||||
('content_id', orm['workflows.StateObjectRelation:content_id']),
|
||||
('state', orm['workflows.StateObjectRelation:state']),
|
||||
))
|
||||
db.send_create_signal('workflows', ['StateObjectRelation'])
|
||||
|
||||
# Adding ManyToManyField 'State.transitions'
|
||||
db.create_table('workflows_state_transitions', (
|
||||
('id', models.AutoField(verbose_name='ID', primary_key=True, auto_created=True)),
|
||||
('state', models.ForeignKey(orm.State, null=False)),
|
||||
('transition', models.ForeignKey(orm.Transition, null=False))
|
||||
))
|
||||
|
||||
# Creating unique_together for [content_type, content_id] on WorkflowObjectRelation.
|
||||
db.create_unique('workflows_workflowobjectrelation', ['content_type_id', 'content_id'])
|
||||
|
||||
# Creating unique_together for [content_type, content_id, state] on StateObjectRelation.
|
||||
db.create_unique('workflows_stateobjectrelation', ['content_type_id', 'content_id', 'state_id'])
|
||||
|
||||
# Creating unique_together for [workflow, permission] on WorkflowPermissionRelation.
|
||||
db.create_unique('workflows_workflowpermissionrelation', ['workflow_id', 'permission_id'])
|
||||
|
||||
|
||||
|
||||
def backwards(self, orm):
|
||||
|
||||
# Deleting unique_together for [workflow, permission] on WorkflowPermissionRelation.
|
||||
db.delete_unique('workflows_workflowpermissionrelation', ['workflow_id', 'permission_id'])
|
||||
|
||||
# Deleting unique_together for [content_type, content_id, state] on StateObjectRelation.
|
||||
db.delete_unique('workflows_stateobjectrelation', ['content_type_id', 'content_id', 'state_id'])
|
||||
|
||||
# Deleting unique_together for [content_type, content_id] on WorkflowObjectRelation.
|
||||
db.delete_unique('workflows_workflowobjectrelation', ['content_type_id', 'content_id'])
|
||||
|
||||
# Deleting model 'Workflow'
|
||||
db.delete_table('workflows_workflow')
|
||||
|
||||
# Deleting model 'StatePermissionRelation'
|
||||
db.delete_table('workflows_statepermissionrelation')
|
||||
|
||||
# Deleting model 'StateInheritanceBlock'
|
||||
db.delete_table('workflows_stateinheritanceblock')
|
||||
|
||||
# Deleting model 'WorkflowModelRelation'
|
||||
db.delete_table('workflows_workflowmodelrelation')
|
||||
|
||||
# Deleting model 'WorkflowPermissionRelation'
|
||||
db.delete_table('workflows_workflowpermissionrelation')
|
||||
|
||||
# Deleting model 'State'
|
||||
db.delete_table('workflows_state')
|
||||
|
||||
# Deleting model 'Transition'
|
||||
db.delete_table('workflows_transition')
|
||||
|
||||
# Deleting model 'WorkflowObjectRelation'
|
||||
db.delete_table('workflows_workflowobjectrelation')
|
||||
|
||||
# Deleting model 'StateObjectRelation'
|
||||
db.delete_table('workflows_stateobjectrelation')
|
||||
|
||||
# Dropping ManyToManyField 'State.transitions'
|
||||
db.delete_table('workflows_state_transitions')
|
||||
|
||||
|
||||
|
||||
models = {
|
||||
'contenttypes.contenttype': {
|
||||
'Meta': {'unique_together': "(('app_label', 'model'),)", 'db_table': "'django_content_type'"},
|
||||
'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'})
|
||||
},
|
||||
'permissions.permission': {
|
||||
'codename': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
|
||||
'content_types': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['contenttypes.ContentType']", 'null': 'True', 'blank': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
|
||||
},
|
||||
'permissions.role': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
|
||||
},
|
||||
'workflows.state': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'transitions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['workflows.Transition']", 'null': 'True', 'blank': 'True'}),
|
||||
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'states'", 'to': "orm['workflows.Workflow']"})
|
||||
},
|
||||
'workflows.stateinheritanceblock': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']"}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.State']"})
|
||||
},
|
||||
'workflows.stateobjectrelation': {
|
||||
'Meta': {'unique_together': "(('content_type', 'content_id', 'state'),)"},
|
||||
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'state_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.State']"})
|
||||
},
|
||||
'workflows.statepermissionrelation': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']"}),
|
||||
'role': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Role']"}),
|
||||
'state': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.State']"})
|
||||
},
|
||||
'workflows.transition': {
|
||||
'condition': ('django.db.models.fields.CharField', [], {'max_length': '100', 'blank': 'True'}),
|
||||
'destination': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'destination_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
|
||||
'permission': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['permissions.Permission']", 'null': 'True', 'blank': 'True'}),
|
||||
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'transitions'", 'to': "orm['workflows.Workflow']"})
|
||||
},
|
||||
'workflows.workflow': {
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'initial_state': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_state'", 'null': 'True', 'to': "orm['workflows.State']"}),
|
||||
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'}),
|
||||
'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['permissions.Permission']", 'symmetrical': 'False'})
|
||||
},
|
||||
'workflows.workflowmodelrelation': {
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']", 'unique': 'True'}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'wmrs'", 'to': "orm['workflows.Workflow']"})
|
||||
},
|
||||
'workflows.workflowobjectrelation': {
|
||||
'Meta': {'unique_together': "(('content_type', 'content_id'),)"},
|
||||
'content_id': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True', 'blank': 'True'}),
|
||||
'content_type': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'workflow_object'", 'null': 'True', 'to': "orm['contenttypes.ContentType']"}),
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'wors'", 'to': "orm['workflows.Workflow']"})
|
||||
},
|
||||
'workflows.workflowpermissionrelation': {
|
||||
'Meta': {'unique_together': "(('workflow', 'permission'),)"},
|
||||
'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
|
||||
'permission': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'permissions'", 'to': "orm['permissions.Permission']"}),
|
||||
'workflow': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['workflows.Workflow']"})
|
||||
}
|
||||
}
|
||||
|
||||
complete_apps = ['workflows']
|
|
@ -1,357 +0,0 @@
|
|||
from django.db import models
|
||||
|
||||
# django imports
|
||||
from django.contrib.contenttypes import generic
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.utils.translation import ugettext_lazy as _
|
||||
|
||||
# permissions imports
|
||||
import permissions.utils
|
||||
from permissions.models import Permission
|
||||
from permissions.models import Role
|
||||
|
||||
class Workflow(models.Model):
|
||||
"""A workflow consists of a sequence of connected (through transitions)
|
||||
states. It can be assigned to a model and / or model instances. If a
|
||||
model instance has a workflow it takes precendence over the model's
|
||||
workflow.
|
||||
|
||||
**Attributes:**
|
||||
|
||||
model
|
||||
The model the workflow belongs to. Can be any
|
||||
|
||||
content
|
||||
The object the workflow belongs to.
|
||||
|
||||
name
|
||||
The unique name of the workflow.
|
||||
|
||||
states
|
||||
The states of the workflow.
|
||||
|
||||
initial_state
|
||||
The initial state the model / content gets if created.
|
||||
|
||||
"""
|
||||
name = models.CharField(_(u"Name"), max_length=100, unique=True)
|
||||
initial_state = models.ForeignKey("State", related_name="workflow_state", blank=True, null=True)
|
||||
permissions = models.ManyToManyField(Permission, symmetrical=False, through="WorkflowPermissionRelation")
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
def get_initial_state(self):
|
||||
"""Returns the initial state of the workflow. Takes the first one if
|
||||
no state has been defined.
|
||||
"""
|
||||
if self.initial_state:
|
||||
return self.initial_state
|
||||
else:
|
||||
try:
|
||||
return self.states.all()[0]
|
||||
except IndexError:
|
||||
return None
|
||||
|
||||
def get_objects(self):
|
||||
"""Returns all objects which have this workflow assigned. Globally
|
||||
(via the object's content type) or locally (via the object itself).
|
||||
"""
|
||||
import workflows.utils
|
||||
objs = []
|
||||
|
||||
# Get all objects whose content type has this workflow
|
||||
for wmr in WorkflowModelRelation.objects.filter(workflow=self):
|
||||
ctype = wmr.content_type
|
||||
# We have also to check whether the global workflow is not
|
||||
# overwritten.
|
||||
for obj in ctype.model_class().objects.all():
|
||||
if workflows.utils.get_workflow(obj) == self:
|
||||
objs.append(obj)
|
||||
|
||||
# Get all objects whose local workflow this workflow
|
||||
for wor in WorkflowObjectRelation.objects.filter(workflow=self):
|
||||
if wor.content not in objs:
|
||||
objs.append(wor.content)
|
||||
|
||||
return objs
|
||||
|
||||
def set_to(self, ctype_or_obj):
|
||||
"""Sets the workflow to passed content type or object. See the specific
|
||||
methods for more information.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
ctype_or_obj
|
||||
The content type or the object to which the workflow should be set.
|
||||
Can be either a ContentType instance or any Django model instance.
|
||||
"""
|
||||
if isinstance(ctype_or_obj, ContentType):
|
||||
return self.set_to_model(ctype_or_obj)
|
||||
else:
|
||||
return self.set_to_object(ctype_or_obj)
|
||||
|
||||
def set_to_model(self, ctype):
|
||||
"""Sets the workflow to the passed content type. If the content
|
||||
type has already an assigned workflow the workflow is overwritten.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
ctype
|
||||
The content type which gets the workflow. Can be any Django model
|
||||
instance.
|
||||
"""
|
||||
try:
|
||||
wor = WorkflowModelRelation.objects.get(content_type=ctype)
|
||||
except WorkflowModelRelation.DoesNotExist:
|
||||
WorkflowModelRelation.objects.create(content_type=ctype, workflow=self)
|
||||
else:
|
||||
wor.workflow = self
|
||||
wor.save()
|
||||
|
||||
def set_to_object(self, obj):
|
||||
"""Sets the workflow to the passed object.
|
||||
|
||||
If the object has already the given workflow nothing happens. Otherwise
|
||||
the workflow is set to the objectthe state is set to the workflow's
|
||||
initial state.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
obj
|
||||
The object which gets the workflow.
|
||||
"""
|
||||
import workflows.utils
|
||||
|
||||
ctype = ContentType.objects.get_for_model(obj)
|
||||
try:
|
||||
wor = WorkflowObjectRelation.objects.get(content_type=ctype, content_id=obj.pk)
|
||||
except WorkflowObjectRelation.DoesNotExist:
|
||||
WorkflowObjectRelation.objects.create(content = obj, workflow=self)
|
||||
workflows.utils.set_state(obj, self.initial_state)
|
||||
else:
|
||||
if wor.workflow != self:
|
||||
wor.workflow = self
|
||||
wor.save()
|
||||
workflows.utils.set_state(self.initial_state)
|
||||
|
||||
class State(models.Model):
|
||||
"""A certain state within workflow.
|
||||
|
||||
**Attributes:**
|
||||
|
||||
name
|
||||
The unique name of the state within the workflow.
|
||||
|
||||
workflow
|
||||
The workflow to which the state belongs.
|
||||
|
||||
transitions
|
||||
The transitions of a workflow state.
|
||||
|
||||
"""
|
||||
name = models.CharField(_(u"Name"), max_length=100)
|
||||
workflow = models.ForeignKey(Workflow, verbose_name=_(u"Workflow"), related_name="states")
|
||||
transitions = models.ManyToManyField("Transition", verbose_name=_(u"Transitions"), blank=True, null=True, related_name="states")
|
||||
|
||||
class Meta:
|
||||
ordering = ("name", )
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s (%s)" % (self.name, self.workflow.name)
|
||||
|
||||
def get_allowed_transitions(self, obj, user):
|
||||
"""Returns all allowed transitions for passed object and user.
|
||||
"""
|
||||
transitions = []
|
||||
for transition in self.transitions.all():
|
||||
permission = transition.permission
|
||||
if permission is None:
|
||||
transitions.append(transition)
|
||||
else:
|
||||
# First we try to get the objects specific has_permission
|
||||
# method (in case the object inherits from the PermissionBase
|
||||
# class).
|
||||
try:
|
||||
if obj.has_permission(user, permission.codename):
|
||||
transitions.append(transition)
|
||||
except AttributeError:
|
||||
if permissions.utils.has_permission(obj, user, permission.codename):
|
||||
transitions.append(transition)
|
||||
return transitions
|
||||
|
||||
class Transition(models.Model):
|
||||
"""A transition from a source to a destination state. The transition can
|
||||
be used from several source states.
|
||||
|
||||
**Attributes:**
|
||||
|
||||
name
|
||||
The unique name of the transition within a workflow.
|
||||
|
||||
workflow
|
||||
The workflow to which the transition belongs. Must be a Workflow
|
||||
instance.
|
||||
|
||||
destination
|
||||
The state after a transition has been processed. Must be a State
|
||||
instance.
|
||||
|
||||
condition
|
||||
The condition when the transition is available. Can be any python
|
||||
expression.
|
||||
|
||||
permission
|
||||
The necessary permission to process the transition. Must be a
|
||||
Permission instance.
|
||||
|
||||
"""
|
||||
name = models.CharField(_(u"Name"), max_length=100)
|
||||
workflow = models.ForeignKey(Workflow, verbose_name=_(u"Workflow"), related_name="transitions")
|
||||
destination = models.ForeignKey(State, verbose_name=_(u"Destination"), null=True, blank=True, related_name="destination_state")
|
||||
condition = models.CharField(_(u"Condition"), blank=True, max_length=100)
|
||||
permission = models.ForeignKey(Permission, verbose_name=_(u"Permission"), blank=True, null=True)
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
class StateObjectRelation(models.Model):
|
||||
"""Stores the workflow state of an object.
|
||||
|
||||
Provides a way to give any object a workflow state without changing the
|
||||
object's model.
|
||||
|
||||
**Attributes:**
|
||||
|
||||
content
|
||||
The object for which the state is stored. This can be any instance of
|
||||
a Django model.
|
||||
|
||||
state
|
||||
The state of content. This must be a State instance.
|
||||
"""
|
||||
content_type = models.ForeignKey(ContentType, verbose_name=_(u"Content type"), related_name="state_object", blank=True, null=True)
|
||||
content_id = models.PositiveIntegerField(_(u"Content id"), blank=True, null=True)
|
||||
content = generic.GenericForeignKey(ct_field="content_type", fk_field="content_id")
|
||||
state = models.ForeignKey(State, verbose_name = _(u"State"))
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s %s - %s" % (self.content_type.name, self.content_id, self.state.name)
|
||||
|
||||
class Meta:
|
||||
unique_together = ("content_type", "content_id", "state")
|
||||
|
||||
class WorkflowObjectRelation(models.Model):
|
||||
"""Stores an workflow of an object.
|
||||
|
||||
Provides a way to give any object a workflow without changing the object's
|
||||
model.
|
||||
|
||||
**Attributes:**
|
||||
|
||||
content
|
||||
The object for which the workflow is stored. This can be any instance of
|
||||
a Django model.
|
||||
|
||||
workflow
|
||||
The workflow which is assigned to an object. This needs to be a workflow
|
||||
instance.
|
||||
"""
|
||||
content_type = models.ForeignKey(ContentType, verbose_name=_(u"Content type"), related_name="workflow_object", blank=True, null=True)
|
||||
content_id = models.PositiveIntegerField(_(u"Content id"), blank=True, null=True)
|
||||
content = generic.GenericForeignKey(ct_field="content_type", fk_field="content_id")
|
||||
workflow = models.ForeignKey(Workflow, verbose_name=_(u"Workflow"), related_name="wors")
|
||||
|
||||
class Meta:
|
||||
unique_together = ("content_type", "content_id")
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s %s - %s" % (self.content_type.name, self.content_id, self.workflow.name)
|
||||
|
||||
class WorkflowModelRelation(models.Model):
|
||||
"""Stores an workflow for a model (ContentType).
|
||||
|
||||
Provides a way to give any object a workflow without changing the model.
|
||||
|
||||
**Attributes:**
|
||||
|
||||
Content Type
|
||||
The content type for which the workflow is stored. This can be any
|
||||
instance of a Django model.
|
||||
|
||||
workflow
|
||||
The workflow which is assigned to an object. This needs to be a
|
||||
workflow instance.
|
||||
"""
|
||||
content_type = models.ForeignKey(ContentType, verbose_name=_(u"Content Type"), unique=True)
|
||||
workflow = models.ForeignKey(Workflow, verbose_name=_(u"Workflow"), related_name="wmrs")
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s - %s" % (self.content_type.name, self.workflow.name)
|
||||
|
||||
# Permissions relation #######################################################
|
||||
|
||||
class WorkflowPermissionRelation(models.Model):
|
||||
"""Stores the permissions for which a workflow is responsible.
|
||||
|
||||
**Attributes:**
|
||||
|
||||
workflow
|
||||
The workflow which is responsible for the permissions. Needs to be a
|
||||
Workflow instance.
|
||||
|
||||
permission
|
||||
The permission for which the workflow is responsible. Needs to be a
|
||||
Permission instance.
|
||||
"""
|
||||
workflow = models.ForeignKey(Workflow)
|
||||
permission = models.ForeignKey(Permission, related_name="permissions")
|
||||
|
||||
class Meta:
|
||||
unique_together = ("workflow", "permission")
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s %s" % (self.workflow.name, self.permission.name)
|
||||
|
||||
class StateInheritanceBlock(models.Model):
|
||||
"""Stores inheritance block for state and permission.
|
||||
|
||||
**Attributes:**
|
||||
|
||||
state
|
||||
The state for which the inheritance is blocked. Needs to be a State
|
||||
instance.
|
||||
|
||||
permission
|
||||
The permission for which the instance is blocked. Needs to be a
|
||||
Permission instance.
|
||||
"""
|
||||
state = models.ForeignKey(State, verbose_name=_(u"State"))
|
||||
permission = models.ForeignKey(Permission, verbose_name=_(u"Permission"))
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s %s" % (self.state.name, self.permission.name)
|
||||
|
||||
class StatePermissionRelation(models.Model):
|
||||
"""Stores granted permission for state and role.
|
||||
|
||||
**Attributes:**
|
||||
|
||||
state
|
||||
The state for which the role has the permission. Needs to be a State
|
||||
instance.
|
||||
|
||||
permission
|
||||
The permission for which the workflow is responsible. Needs to be a
|
||||
Permission instance.
|
||||
|
||||
role
|
||||
The role for which the state has the permission. Needs to be a lfc
|
||||
Role instance.
|
||||
"""
|
||||
state = models.ForeignKey(State, verbose_name=_(u"State"))
|
||||
permission = models.ForeignKey(Permission, verbose_name=_(u"Permission"))
|
||||
role = models.ForeignKey(Role, verbose_name=_(u"Role"))
|
||||
|
||||
def __unicode__(self):
|
||||
return "%s %s %s" % (self.state.name, self.role.name, self.permission.name)
|
|
@ -1,10 +0,0 @@
|
|||
{% load i18n %}
|
||||
<label>{{ state.name }}</label>
|
||||
<select name="transition">
|
||||
{% for transition in transitions %}
|
||||
<option {% if transition.selected %}selected="selected"{% endif %}
|
||||
value="{{ transition.id }}">
|
||||
{{ transition.name }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</select>
|
1
workflows/templatetags/.gitignore
vendored
1
workflows/templatetags/.gitignore
vendored
|
@ -1 +0,0 @@
|
|||
/*.pyc
|
|
@ -1,18 +0,0 @@
|
|||
# django imports
|
||||
from django import template
|
||||
|
||||
# workflows imports
|
||||
import workflows.utils
|
||||
|
||||
register = template.Library()
|
||||
|
||||
@register.inclusion_tag('workflows/transitions.html', takes_context=True)
|
||||
def transitions(context, obj):
|
||||
"""
|
||||
"""
|
||||
request = context.get("request")
|
||||
|
||||
return {
|
||||
"transitions" : workflows.utils.get_allowed_transitions(obj, request.user),
|
||||
"state" : workflows.utils.get_state(obj),
|
||||
}
|
|
@ -1,600 +0,0 @@
|
|||
# django imports
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
from django.contrib.flatpages.models import FlatPage
|
||||
from django.test import TestCase
|
||||
from django.contrib.auth.models import User
|
||||
from django.contrib.sessions.backends.file import SessionStore
|
||||
from django.core.handlers.wsgi import WSGIRequest
|
||||
from django.test.client import Client
|
||||
|
||||
# workflows import
|
||||
import permissions.utils
|
||||
import workflows.utils
|
||||
from workflows.models import State
|
||||
from workflows.models import StateInheritanceBlock
|
||||
from workflows.models import StatePermissionRelation
|
||||
from workflows.models import StateObjectRelation
|
||||
from workflows.models import Transition
|
||||
from workflows.models import Workflow
|
||||
from workflows.models import WorkflowModelRelation
|
||||
from workflows.models import WorkflowObjectRelation
|
||||
from workflows.models import WorkflowPermissionRelation
|
||||
|
||||
class WorkflowTestCase(TestCase):
|
||||
"""Tests a simple workflow without permissions.
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
"""
|
||||
create_workflow(self)
|
||||
|
||||
def test_get_states(self):
|
||||
"""
|
||||
"""
|
||||
states = self.w.states.all()
|
||||
self.assertEqual(states[0], self.private)
|
||||
self.assertEqual(states[1], self.public)
|
||||
|
||||
def test_unicode(self):
|
||||
"""
|
||||
"""
|
||||
self.assertEqual(self.w.__unicode__(), u"Standard")
|
||||
|
||||
class PermissionsTestCase(TestCase):
|
||||
"""Tests a simple workflow with permissions.
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
"""
|
||||
create_workflow(self)
|
||||
|
||||
# Register roles
|
||||
self.anonymous = permissions.utils.register_role("Anonymous")
|
||||
self.owner = permissions.utils.register_role("Owner")
|
||||
|
||||
self.user = User.objects.create(username="john")
|
||||
permissions.utils.add_role(self.user, self.owner)
|
||||
|
||||
# Example content type
|
||||
self.page_1 = FlatPage.objects.create(url="/page-1/", title="Page 1")
|
||||
|
||||
# Registers permissions
|
||||
self.view = permissions.utils.register_permission("View", "view")
|
||||
self.edit = permissions.utils.register_permission("Edit", "edit")
|
||||
|
||||
# Add all permissions which are managed by the workflow
|
||||
wpr = WorkflowPermissionRelation.objects.create(workflow=self.w, permission=self.view)
|
||||
wpr = WorkflowPermissionRelation.objects.create(workflow=self.w, permission=self.edit)
|
||||
|
||||
# Add permissions for single states
|
||||
spr = StatePermissionRelation.objects.create(state=self.public, permission=self.view, role=self.owner)
|
||||
spr = StatePermissionRelation.objects.create(state=self.private, permission=self.view, role=self.owner)
|
||||
spr = StatePermissionRelation.objects.create(state=self.private, permission=self.edit, role=self.owner)
|
||||
|
||||
# Add inheritance block for single states
|
||||
sib = StateInheritanceBlock.objects.create(state=self.private, permission=self.view)
|
||||
sib = StateInheritanceBlock.objects.create(state=self.private, permission=self.edit)
|
||||
sib = StateInheritanceBlock.objects.create(state=self.public, permission=self.edit)
|
||||
|
||||
workflows.utils.set_workflow(self.page_1, self.w)
|
||||
|
||||
def test_set_state(self):
|
||||
"""
|
||||
"""
|
||||
# Permissions
|
||||
result = permissions.utils.has_permission(self.page_1, self.user, "edit")
|
||||
self.assertEqual(result, True)
|
||||
|
||||
result = permissions.utils.has_permission(self.page_1, self.user, "view")
|
||||
self.assertEqual(result, True)
|
||||
|
||||
# Inheritance
|
||||
result = permissions.utils.is_inherited(self.page_1, "view")
|
||||
self.assertEqual(result, False)
|
||||
|
||||
result = permissions.utils.is_inherited(self.page_1, "edit")
|
||||
self.assertEqual(result, False)
|
||||
|
||||
# Change state
|
||||
workflows.utils.set_state(self.page_1, self.public)
|
||||
|
||||
# Permissions
|
||||
result = permissions.utils.has_permission(self.page_1, self.user, "edit")
|
||||
self.assertEqual(result, False)
|
||||
|
||||
result = permissions.utils.has_permission(self.page_1, self.user, "view")
|
||||
self.assertEqual(result, True)
|
||||
|
||||
# Inheritance
|
||||
result = permissions.utils.is_inherited(self.page_1, "view")
|
||||
self.assertEqual(result, True)
|
||||
|
||||
result = permissions.utils.is_inherited(self.page_1, "edit")
|
||||
self.assertEqual(result, False)
|
||||
|
||||
def test_set_initial_state(self):
|
||||
"""
|
||||
"""
|
||||
state = workflows.utils.get_state(self.page_1)
|
||||
self.assertEqual(state.name, self.private.name)
|
||||
|
||||
workflows.utils.do_transition(self.page_1, self.make_public, self.user)
|
||||
state = workflows.utils.get_state(self.page_1)
|
||||
self.assertEqual(state.name, self.public.name)
|
||||
|
||||
workflows.utils.set_initial_state(self.page_1)
|
||||
state = workflows.utils.get_state(self.page_1)
|
||||
self.assertEqual(state.name, self.private.name)
|
||||
|
||||
def test_do_transition(self):
|
||||
"""
|
||||
"""
|
||||
state = workflows.utils.get_state(self.page_1)
|
||||
self.assertEqual(state.name, self.private.name)
|
||||
|
||||
# by transition
|
||||
workflows.utils.do_transition(self.page_1, self.make_public, self.user)
|
||||
|
||||
state = workflows.utils.get_state(self.page_1)
|
||||
self.assertEqual(state.name, self.public.name)
|
||||
|
||||
# by name
|
||||
workflows.utils.do_transition(self.page_1, "Make private", self.user)
|
||||
|
||||
state = workflows.utils.get_state(self.page_1)
|
||||
self.assertEqual(state.name, self.private.name)
|
||||
|
||||
# name which does not exist
|
||||
result = workflows.utils.do_transition(self.page_1, "Make pending", self.user)
|
||||
self.assertEqual(result, False)
|
||||
|
||||
wrong = Transition.objects.create(name="Wrong", workflow=self.w, destination = self.public)
|
||||
|
||||
# name which does not exist
|
||||
result = workflows.utils.do_transition(self.page_1, wrong, self.user)
|
||||
self.assertEqual(result, False)
|
||||
|
||||
class UtilsTestCase(TestCase):
|
||||
"""Tests various methods of the utils module.
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
"""
|
||||
create_workflow(self)
|
||||
self.user = User.objects.create()
|
||||
|
||||
def test_workflow(self):
|
||||
"""
|
||||
"""
|
||||
workflows.utils.set_workflow(self.user, self.w)
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, self.w)
|
||||
|
||||
def test_state(self):
|
||||
"""
|
||||
"""
|
||||
result = workflows.utils.get_state(self.user)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
workflows.utils.set_workflow(self.user, self.w)
|
||||
result = workflows.utils.get_state(self.user)
|
||||
self.assertEqual(result, self.w.initial_state)
|
||||
|
||||
def test_set_workflow_1(self):
|
||||
"""Set worklow by object
|
||||
"""
|
||||
ctype = ContentType.objects.get_for_model(self.user)
|
||||
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
wp = Workflow.objects.create(name="Portal")
|
||||
|
||||
# Set for model
|
||||
workflows.utils.set_workflow_for_model(ctype, wp)
|
||||
|
||||
result = workflows.utils.get_workflow_for_model(ctype)
|
||||
self.assertEqual(result, wp)
|
||||
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, wp)
|
||||
|
||||
# Set for object
|
||||
workflows.utils.set_workflow_for_object(self.user, self.w)
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, self.w)
|
||||
|
||||
# The model still have wp
|
||||
result = workflows.utils.get_workflow_for_model(ctype)
|
||||
self.assertEqual(result, wp)
|
||||
|
||||
def test_set_workflow_2(self):
|
||||
"""Set worklow by name
|
||||
"""
|
||||
ctype = ContentType.objects.get_for_model(self.user)
|
||||
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
wp = Workflow.objects.create(name="Portal")
|
||||
|
||||
# Set for model
|
||||
workflows.utils.set_workflow_for_model(ctype, "Portal")
|
||||
|
||||
result = workflows.utils.get_workflow_for_model(ctype)
|
||||
self.assertEqual(result, wp)
|
||||
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, wp)
|
||||
|
||||
# Set for object
|
||||
workflows.utils.set_workflow_for_object(self.user, "Standard")
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, self.w)
|
||||
|
||||
# The model still have wp
|
||||
result = workflows.utils.get_workflow_for_model(ctype)
|
||||
self.assertEqual(result, wp)
|
||||
|
||||
# Workflow which does not exist
|
||||
result = workflows.utils.set_workflow_for_model(ctype, "Wrong")
|
||||
self.assertEqual(result, False)
|
||||
|
||||
result = workflows.utils.set_workflow_for_object(self.user, "Wrong")
|
||||
self.assertEqual(result, False)
|
||||
|
||||
def test_get_objects_for_workflow_1(self):
|
||||
"""Workflow is added to object.
|
||||
"""
|
||||
result = workflows.utils.get_objects_for_workflow(self.w)
|
||||
self.assertEqual(result, [])
|
||||
|
||||
workflows.utils.set_workflow(self.user, self.w)
|
||||
result = workflows.utils.get_objects_for_workflow(self.w)
|
||||
self.assertEqual(result, [self.user])
|
||||
|
||||
def test_get_objects_for_workflow_2(self):
|
||||
"""Workflow is added to content type.
|
||||
"""
|
||||
result = workflows.utils.get_objects_for_workflow(self.w)
|
||||
self.assertEqual(result, [])
|
||||
|
||||
ctype = ContentType.objects.get_for_model(self.user)
|
||||
workflows.utils.set_workflow(ctype, self.w)
|
||||
result = workflows.utils.get_objects_for_workflow(self.w)
|
||||
self.assertEqual(result, [self.user])
|
||||
|
||||
def test_get_objects_for_workflow_3(self):
|
||||
"""Workflow is added to content type and object.
|
||||
"""
|
||||
result = workflows.utils.get_objects_for_workflow(self.w)
|
||||
self.assertEqual(result, [])
|
||||
|
||||
workflows.utils.set_workflow(self.user, self.w)
|
||||
result = workflows.utils.get_objects_for_workflow(self.w)
|
||||
self.assertEqual(result, [self.user])
|
||||
|
||||
ctype = ContentType.objects.get_for_model(self.user)
|
||||
workflows.utils.set_workflow(ctype, self.w)
|
||||
result = workflows.utils.get_objects_for_workflow(self.w)
|
||||
self.assertEqual(result, [self.user])
|
||||
|
||||
def test_get_objects_for_workflow_4(self):
|
||||
"""Get workflow by name
|
||||
"""
|
||||
result = workflows.utils.get_objects_for_workflow("Standard")
|
||||
self.assertEqual(result, [])
|
||||
|
||||
workflows.utils.set_workflow(self.user, self.w)
|
||||
result = workflows.utils.get_objects_for_workflow("Standard")
|
||||
self.assertEqual(result, [self.user])
|
||||
|
||||
# Workflow which does not exist
|
||||
result = workflows.utils.get_objects_for_workflow("Wrong")
|
||||
self.assertEqual(result, [])
|
||||
|
||||
def test_remove_workflow_from_model(self):
|
||||
"""
|
||||
"""
|
||||
ctype = ContentType.objects.get_for_model(self.user)
|
||||
|
||||
result = workflows.utils.get_workflow(ctype)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
workflows.utils.set_workflow_for_model(ctype, self.w)
|
||||
|
||||
result = workflows.utils.get_workflow_for_model(ctype)
|
||||
self.assertEqual(result, self.w)
|
||||
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, self.w)
|
||||
|
||||
workflows.utils.remove_workflow_from_model(ctype)
|
||||
|
||||
result = workflows.utils.get_workflow_for_model(ctype)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
result = workflows.utils.get_workflow_for_object(self.user)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
def test_remove_workflow_from_object(self):
|
||||
"""
|
||||
"""
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
workflows.utils.set_workflow_for_object(self.user, self.w)
|
||||
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, self.w)
|
||||
|
||||
result = workflows.utils.remove_workflow_from_object(self.user)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
def test_remove_workflow_1(self):
|
||||
"""Removes workflow from model
|
||||
"""
|
||||
ctype = ContentType.objects.get_for_model(self.user)
|
||||
|
||||
result = workflows.utils.get_workflow(ctype)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
workflows.utils.set_workflow_for_model(ctype, self.w)
|
||||
|
||||
result = workflows.utils.get_workflow_for_model(ctype)
|
||||
self.assertEqual(result, self.w)
|
||||
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, self.w)
|
||||
|
||||
workflows.utils.remove_workflow(ctype)
|
||||
|
||||
result = workflows.utils.get_workflow_for_model(ctype)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
result = workflows.utils.get_workflow_for_object(self.user)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
def test_remove_workflow_2(self):
|
||||
"""Removes workflow from object
|
||||
"""
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
workflows.utils.set_workflow_for_object(self.user, self.w)
|
||||
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, self.w)
|
||||
|
||||
result = workflows.utils.remove_workflow(self.user)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
def test_get_allowed_transitions(self):
|
||||
"""Tests get_allowed_transitions method
|
||||
"""
|
||||
page_1 = FlatPage.objects.create(url="/page-1/", title="Page 1")
|
||||
role_1 = permissions.utils.register_role("Role 1")
|
||||
permissions.utils.add_role(self.user, role_1)
|
||||
|
||||
view = permissions.utils.register_permission("Publish", "publish")
|
||||
|
||||
transitions = self.private.get_allowed_transitions(page_1, self.user)
|
||||
self.assertEqual(len(transitions), 1)
|
||||
|
||||
# protect the transition with a permission
|
||||
self.make_public.permission = view
|
||||
self.make_public.save()
|
||||
|
||||
# user has no transition
|
||||
transitions = self.private.get_allowed_transitions(page_1, self.user)
|
||||
self.assertEqual(len(transitions), 0)
|
||||
|
||||
# grant permission
|
||||
permissions.utils.grant_permission(page_1, role_1, view)
|
||||
|
||||
# user has transition again
|
||||
transitions = self.private.get_allowed_transitions(page_1, self.user)
|
||||
self.assertEqual(len(transitions), 1)
|
||||
|
||||
def test_get_workflow_for_object(self):
|
||||
"""
|
||||
"""
|
||||
result = workflows.utils.get_workflow(self.user)
|
||||
self.assertEqual(result, None)
|
||||
|
||||
# Set workflow for a user
|
||||
workflows.utils.set_workflow_for_object(self.user, self.w)
|
||||
|
||||
# Get workflow for the user
|
||||
result = workflows.utils.get_workflow_for_object(self.user)
|
||||
self.assertEqual(result, self.w)
|
||||
|
||||
# Set workflow for a FlatPage
|
||||
page_1 = FlatPage.objects.create(url="/page-1/", title="Page 1")
|
||||
workflows.utils.set_workflow_for_object(page_1, self.w)
|
||||
|
||||
result = workflows.utils.get_workflow_for_object(self.user)
|
||||
self.assertEqual(result, self.w)
|
||||
|
||||
result = workflows.utils.get_workflow_for_object(page_1)
|
||||
self.assertEqual(result, self.w)
|
||||
|
||||
class StateTestCase(TestCase):
|
||||
"""Tests the State model
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
"""
|
||||
create_workflow(self)
|
||||
self.user = User.objects.create()
|
||||
self.role_1 = permissions.utils.register_role("Role 1")
|
||||
permissions.utils.add_role(self.user, self.role_1)
|
||||
self.page_1 = FlatPage.objects.create(url="/page-1/", title="Page 1")
|
||||
|
||||
def test_unicode(self):
|
||||
"""
|
||||
"""
|
||||
self.assertEqual(self.private.__unicode__(), u"Private (Standard)")
|
||||
|
||||
def test_transitions(self):
|
||||
"""
|
||||
"""
|
||||
transitions = self.public.transitions.all()
|
||||
self.assertEqual(len(transitions), 1)
|
||||
self.assertEqual(transitions[0], self.make_private)
|
||||
|
||||
transitions = self.private.transitions.all()
|
||||
self.assertEqual(len(transitions), 1)
|
||||
self.assertEqual(transitions[0], self.make_public)
|
||||
|
||||
def test_get_transitions(self):
|
||||
"""
|
||||
"""
|
||||
transitions = self.private.get_allowed_transitions(self.page_1, self.user)
|
||||
self.assertEqual(len(transitions), 1)
|
||||
self.assertEqual(transitions[0], self.make_public)
|
||||
|
||||
transitions = self.public.get_allowed_transitions(self.page_1, self.user)
|
||||
self.assertEqual(len(transitions), 1)
|
||||
self.assertEqual(transitions[0], self.make_private)
|
||||
|
||||
def test_get_allowed_transitions(self):
|
||||
"""
|
||||
"""
|
||||
self.view = permissions.utils.register_permission("Publish", "publish")
|
||||
transitions = self.private.get_allowed_transitions(self.page_1, self.user)
|
||||
self.assertEqual(len(transitions), 1)
|
||||
|
||||
# protect the transition with a permission
|
||||
self.make_public.permission = self.view
|
||||
self.make_public.save()
|
||||
|
||||
# user has no transition
|
||||
transitions = self.private.get_allowed_transitions(self.page_1, self.user)
|
||||
self.assertEqual(len(transitions), 0)
|
||||
|
||||
# grant permission
|
||||
permissions.utils.grant_permission(self.page_1, self.role_1, self.view)
|
||||
|
||||
# user has transition again
|
||||
transitions = self.private.get_allowed_transitions(self.page_1, self.user)
|
||||
self.assertEqual(len(transitions), 1)
|
||||
|
||||
class TransitionTestCase(TestCase):
|
||||
"""Tests the Transition model
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
"""
|
||||
create_workflow(self)
|
||||
|
||||
def test_unicode(self):
|
||||
"""
|
||||
"""
|
||||
self.assertEqual(self.make_private.__unicode__(), u"Make private")
|
||||
|
||||
class RelationsTestCase(TestCase):
|
||||
"""Tests various Relations models.
|
||||
"""
|
||||
def setUp(self):
|
||||
"""
|
||||
"""
|
||||
create_workflow(self)
|
||||
self.page_1 = FlatPage.objects.create(url="/page-1/", title="Page 1")
|
||||
|
||||
def test_unicode(self):
|
||||
"""
|
||||
"""
|
||||
# WorkflowObjectRelation
|
||||
workflows.utils.set_workflow(self.page_1, self.w)
|
||||
wor = WorkflowObjectRelation.objects.filter()[0]
|
||||
self.assertEqual(wor.__unicode__(), "flat page 1 - Standard")
|
||||
|
||||
# StateObjectRelation
|
||||
workflows.utils.set_state(self.page_1, self.public)
|
||||
sor = StateObjectRelation.objects.filter()[0]
|
||||
self.assertEqual(sor.__unicode__(), "flat page 1 - Public")
|
||||
|
||||
# WorkflowModelRelation
|
||||
ctype = ContentType.objects.get_for_model(self.page_1)
|
||||
workflows.utils.set_workflow(ctype, self.w)
|
||||
wmr = WorkflowModelRelation.objects.filter()[0]
|
||||
self.assertEqual(wmr.__unicode__(), "flat page - Standard")
|
||||
|
||||
# WorkflowPermissionRelation
|
||||
self.view = permissions.utils.register_permission("View", "view")
|
||||
wpr = WorkflowPermissionRelation.objects.create(workflow=self.w, permission=self.view)
|
||||
self.assertEqual(wpr.__unicode__(), "Standard View")
|
||||
|
||||
# StatePermissionRelation
|
||||
self.owner = permissions.utils.register_role("Owner")
|
||||
spr = StatePermissionRelation.objects.create(state=self.public, permission=self.view, role=self.owner)
|
||||
self.assertEqual(spr.__unicode__(), "Public Owner View")
|
||||
|
||||
# Helpers ####################################################################
|
||||
|
||||
def create_workflow(self):
|
||||
self.w = Workflow.objects.create(name="Standard")
|
||||
|
||||
self.private = State.objects.create(name="Private", workflow= self.w)
|
||||
self.public = State.objects.create(name="Public", workflow= self.w)
|
||||
|
||||
self.make_public = Transition.objects.create(name="Make public", workflow=self.w, destination = self.public)
|
||||
self.make_private = Transition.objects.create(name="Make private", workflow=self.w, destination = self.private)
|
||||
|
||||
self.private.transitions.add(self.make_public)
|
||||
self.public.transitions.add(self.make_private)
|
||||
|
||||
self.w.initial_state = self.private
|
||||
self.w.save()
|
||||
|
||||
# Taken from "http://www.djangosnippets.org/snippets/963/"
|
||||
class RequestFactory(Client):
|
||||
"""
|
||||
Class that lets you create mock Request objects for use in testing.
|
||||
|
||||
Usage:
|
||||
|
||||
rf = RequestFactory()
|
||||
get_request = rf.get('/hello/')
|
||||
post_request = rf.post('/submit/', {'foo': 'bar'})
|
||||
|
||||
This class re-uses the django.test.client.Client interface, docs here:
|
||||
http://www.djangoproject.com/documentation/testing/#the-test-client
|
||||
|
||||
Once you have a request object you can pass it to any view function,
|
||||
just as if that view had been hooked up using a URLconf.
|
||||
|
||||
"""
|
||||
def request(self, **request):
|
||||
"""
|
||||
Similar to parent class, but returns the request object as soon as it
|
||||
has created it.
|
||||
"""
|
||||
environ = {
|
||||
'HTTP_COOKIE': self.cookies,
|
||||
'PATH_INFO': '/',
|
||||
'QUERY_STRING': '',
|
||||
'REQUEST_METHOD': 'GET',
|
||||
'SCRIPT_NAME': '',
|
||||
'SERVER_NAME': 'testserver',
|
||||
'SERVER_PORT': 80,
|
||||
'SERVER_PROTOCOL': 'HTTP/1.1',
|
||||
}
|
||||
environ.update(self.defaults)
|
||||
environ.update(request)
|
||||
return WSGIRequest(environ)
|
||||
|
||||
def create_request():
|
||||
"""
|
||||
"""
|
||||
rf = RequestFactory()
|
||||
request = rf.get('/')
|
||||
request.session = SessionStore()
|
||||
|
||||
user = User()
|
||||
user.is_superuser = True
|
||||
user.save()
|
||||
request.user = user
|
||||
|
||||
return request
|
|
@ -1,7 +0,0 @@
|
|||
from django.conf.urls.defaults import *
|
||||
|
||||
# URL patterns for django-workflows
|
||||
|
||||
urlpatterns = patterns('django-workflows.views',
|
||||
# Add url patterns here
|
||||
)
|
|
@ -1,351 +0,0 @@
|
|||
# django imports
|
||||
from django.contrib.contenttypes.models import ContentType
|
||||
|
||||
# workflows imports
|
||||
from permissions.models import ObjectPermission
|
||||
from permissions.models import ObjectPermissionInheritanceBlock
|
||||
from workflows.models import StateInheritanceBlock
|
||||
from workflows.models import StateObjectRelation
|
||||
from workflows.models import StatePermissionRelation
|
||||
from workflows.models import Transition
|
||||
from workflows.models import Workflow
|
||||
from workflows.models import WorkflowModelRelation
|
||||
from workflows.models import WorkflowObjectRelation
|
||||
from workflows.models import WorkflowPermissionRelation
|
||||
|
||||
# permissions imports
|
||||
import permissions.utils
|
||||
|
||||
def get_objects_for_workflow(workflow):
|
||||
"""Returns all objects which have passed workflow.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
workflow
|
||||
The workflow for which the objects are returned. Can be a Workflow
|
||||
instance or a string with the workflow name.
|
||||
"""
|
||||
if not isinstance(workflow, Workflow):
|
||||
try:
|
||||
workflow = Workflow.objects.get(name=workflow)
|
||||
except Workflow.DoesNotExist:
|
||||
return []
|
||||
|
||||
return workflow.get_objects()
|
||||
|
||||
def remove_workflow(ctype_or_obj):
|
||||
"""Removes the workflow from the passed content type or object. After this
|
||||
function has been called the content type or object has no workflow
|
||||
anymore.
|
||||
|
||||
If ctype_or_obj is an object the workflow is removed from the object not
|
||||
from the belonging content type.
|
||||
|
||||
If ctype_or_obj is an content type the workflow is removed from the
|
||||
content type not from instances of the content type (if they have an own
|
||||
workflow)
|
||||
|
||||
ctype_or_obj
|
||||
The content type or the object to which the passed workflow should be
|
||||
set. Can be either a ContentType instance or any LFC Django model
|
||||
instance.
|
||||
"""
|
||||
if isinstance(ctype_or_obj, ContentType):
|
||||
remove_workflow_from_model(ctype_or_obj)
|
||||
else:
|
||||
remove_workflow_from_object(ctype_or_obj)
|
||||
|
||||
def remove_workflow_from_model(ctype):
|
||||
"""Removes the workflow from passed content type. After this function has
|
||||
been called the content type has no workflow anymore (the instances might
|
||||
have own ones).
|
||||
|
||||
ctype
|
||||
The content type from which the passed workflow should be removed.
|
||||
Must be a ContentType instance.
|
||||
"""
|
||||
# First delete all states, inheritance blocks and permissions from ctype's
|
||||
# instances which have passed workflow.
|
||||
workflow = get_workflow_for_model(ctype)
|
||||
for obj in get_objects_for_workflow(workflow):
|
||||
try:
|
||||
ctype = ContentType.objects.get_for_model(obj)
|
||||
sor = StateObjectRelation.objects.get(content_id=obj.pk, content_type=ctype)
|
||||
except StateObjectRelation.DoesNotExist:
|
||||
pass
|
||||
else:
|
||||
sor.delete()
|
||||
|
||||
# Reset all permissions
|
||||
permissions.utils.reset(obj)
|
||||
|
||||
try:
|
||||
wmr = WorkflowModelRelation.objects.get(content_type=ctype)
|
||||
except WorkflowModelRelation.DoesNotExist:
|
||||
pass
|
||||
else:
|
||||
wmr.delete()
|
||||
|
||||
def remove_workflow_from_object(obj):
|
||||
"""Removes the workflow from the passed object. After this function has
|
||||
been called the object has no *own* workflow anymore (it might have one
|
||||
via its content type).
|
||||
|
||||
obj
|
||||
The object from which the passed workflow should be set. Must be a
|
||||
Django Model instance.
|
||||
"""
|
||||
try:
|
||||
wor = WorkflowObjectRelation.objects.get(content_type=obj)
|
||||
except WorkflowObjectRelation.DoesNotExist:
|
||||
pass
|
||||
else:
|
||||
wor.delete()
|
||||
|
||||
# Reset all permissions
|
||||
permissions.utils.reset(obj)
|
||||
|
||||
# Set initial of object's content types workflow (if there is one)
|
||||
set_initial_state(obj)
|
||||
|
||||
def set_workflow(ctype_or_obj, workflow):
|
||||
"""Sets the workflow for passed content type or object. See the specific
|
||||
methods for more information.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
workflow
|
||||
The workflow which should be set to the object or model.
|
||||
|
||||
ctype_or_obj
|
||||
The content type or the object to which the passed workflow should be
|
||||
set. Can be either a ContentType instance or any Django model
|
||||
instance.
|
||||
"""
|
||||
return workflow.set_to(ctype_or_obj)
|
||||
|
||||
def set_workflow_for_object(obj, workflow):
|
||||
"""Sets the passed workflow to the passed object.
|
||||
|
||||
If the object has already the given workflow nothing happens. Otherwise
|
||||
the object gets the passed workflow and the state is set to the workflow's
|
||||
initial state.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
workflow
|
||||
The workflow which should be set to the object. Can be a Workflow
|
||||
instance or a string with the workflow name.
|
||||
|
||||
obj
|
||||
The object which gets the passed workflow.
|
||||
"""
|
||||
if isinstance(workflow, Workflow) == False:
|
||||
try:
|
||||
workflow = Workflow.objects.get(name=workflow)
|
||||
except Workflow.DoesNotExist:
|
||||
return False
|
||||
|
||||
workflow.set_to_object(obj)
|
||||
|
||||
def set_workflow_for_model(ctype, workflow):
|
||||
"""Sets the passed workflow to the passed content type. If the content
|
||||
type has already an assigned workflow the workflow is overwritten.
|
||||
|
||||
The objects which had the old workflow must updated explicitely.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
workflow
|
||||
The workflow which should be set to passend content type. Must be a
|
||||
Workflow instance.
|
||||
|
||||
ctype
|
||||
The content type to which the passed workflow should be assigned. Can
|
||||
be any Django model instance
|
||||
"""
|
||||
if isinstance(workflow, Workflow) == False:
|
||||
try:
|
||||
workflow = Workflow.objects.get(name=workflow)
|
||||
except Workflow.DoesNotExist:
|
||||
return False
|
||||
|
||||
workflow.set_to_model(ctype)
|
||||
|
||||
def get_workflow(obj):
|
||||
"""Returns the workflow for the passed object. It takes it either from
|
||||
the passed object or - if the object doesn't have a workflow - from the
|
||||
passed object's ContentType.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
object
|
||||
The object for which the workflow should be returend. Can be any
|
||||
Django model instance.
|
||||
"""
|
||||
workflow = get_workflow_for_object(obj)
|
||||
if workflow is not None:
|
||||
return workflow
|
||||
|
||||
ctype = ContentType.objects.get_for_model(obj)
|
||||
return get_workflow_for_model(ctype)
|
||||
|
||||
def get_workflow_for_object(obj):
|
||||
"""Returns the workflow for the passed object.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
obj
|
||||
The object for which the workflow should be returned. Can be any
|
||||
Django model instance.
|
||||
"""
|
||||
try:
|
||||
ctype = ContentType.objects.get_for_model(obj)
|
||||
wor = WorkflowObjectRelation.objects.get(content_id=obj.pk, content_type=ctype)
|
||||
except WorkflowObjectRelation.DoesNotExist:
|
||||
return None
|
||||
else:
|
||||
return wor.workflow
|
||||
|
||||
def get_workflow_for_model(ctype):
|
||||
"""Returns the workflow for the passed model.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
ctype
|
||||
The content type for which the workflow should be returned. Must be
|
||||
a Django ContentType instance.
|
||||
"""
|
||||
try:
|
||||
wor = WorkflowModelRelation.objects.get(content_type=ctype)
|
||||
except WorkflowModelRelation.DoesNotExist:
|
||||
return None
|
||||
else:
|
||||
return wor.workflow
|
||||
|
||||
def get_state(obj):
|
||||
"""Returns the current workflow state for the passed object.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
obj
|
||||
The object for which the workflow state should be returned. Can be any
|
||||
Django model instance.
|
||||
"""
|
||||
ctype = ContentType.objects.get_for_model(obj)
|
||||
try:
|
||||
sor = StateObjectRelation.objects.get(content_type=ctype, content_id=obj.pk)
|
||||
except StateObjectRelation.DoesNotExist:
|
||||
return None
|
||||
else:
|
||||
return sor.state
|
||||
|
||||
def set_state(obj, state):
|
||||
"""Sets the state for the passed object to the passed state and updates
|
||||
the permissions for the object.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
obj
|
||||
The object for which the workflow state should be set. Can be any
|
||||
Django model instance.
|
||||
|
||||
state
|
||||
The state which should be set to the passed object.
|
||||
"""
|
||||
if not state:
|
||||
remove_state(obj)
|
||||
else:
|
||||
ctype = ContentType.objects.get_for_model(obj)
|
||||
try:
|
||||
sor = StateObjectRelation.objects.get(content_type=ctype, content_id=obj.pk)
|
||||
except StateObjectRelation.DoesNotExist:
|
||||
sor = StateObjectRelation.objects.create(content=obj, state=state)
|
||||
else:
|
||||
sor.state = state
|
||||
sor.save()
|
||||
update_permissions(obj)
|
||||
|
||||
def remove_state(obj):
|
||||
"""Removes the current state for the passed object.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
obj
|
||||
The object for which the workflow state should be set. Can be any
|
||||
Django model instance.
|
||||
|
||||
"""
|
||||
ctype = ContentType.objects.get_for_model(obj)
|
||||
try:
|
||||
sor = StateObjectRelation.objects.get(content_type=ctype, content_id=obj.pk)
|
||||
sor.delete()
|
||||
except StateObjectRelation.DoesNotExist:
|
||||
pass
|
||||
update_permissions(obj)
|
||||
|
||||
def set_initial_state(obj):
|
||||
"""Sets the initial state to the passed object.
|
||||
"""
|
||||
wf = get_workflow(obj)
|
||||
if wf is not None:
|
||||
set_state(obj, wf.get_initial_state())
|
||||
|
||||
def get_allowed_transitions(obj, user):
|
||||
"""Returns all allowed transitions for passed object and user. Takes the
|
||||
current state of the object into account.
|
||||
|
||||
**Parameters:**
|
||||
|
||||
obj
|
||||
The object for which the transitions should be returned.
|
||||
|
||||
user
|
||||
The user for which the transitions are allowed.
|
||||
"""
|
||||
state = get_state(obj)
|
||||
if state is None:
|
||||
return []
|
||||
|
||||
return state.get_allowed_transitions(obj, user)
|
||||
|
||||
def do_transition(obj, transition, user):
|
||||
"""Processes the passed transition to the passed object (if allowed).
|
||||
"""
|
||||
if not isinstance(transition, Transition):
|
||||
try:
|
||||
transition = Transition.objects.get(name=transition)
|
||||
except Transition.DoesNotExist:
|
||||
return False
|
||||
|
||||
transitions = get_allowed_transitions(obj, user)
|
||||
if transition in transitions:
|
||||
set_state(obj, transition.destination)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
def update_permissions(obj):
|
||||
"""Updates the permissions of the passed object according to the object's
|
||||
current workflow state.
|
||||
"""
|
||||
workflow = get_workflow(obj)
|
||||
state = get_state(obj)
|
||||
|
||||
# Remove all permissions for the workflow
|
||||
ct = ContentType.objects.get_for_model(obj)
|
||||
ps = [wpr.permission for wpr in WorkflowPermissionRelation.objects.filter(workflow=workflow)]
|
||||
|
||||
ObjectPermission.objects.filter(content_type = ct, content_id=obj.pk, permission__in=ps).delete()
|
||||
|
||||
# Grant permission for the state
|
||||
for spr in StatePermissionRelation.objects.filter(state=state):
|
||||
permissions.utils.grant_permission(obj, spr.role, spr.permission)
|
||||
|
||||
# Remove all inheritance blocks from the object
|
||||
ObjectPermissionInheritanceBlock.objects.filter(
|
||||
content_type = ct, content_id=obj.pk, permission__in=ps).delete()
|
||||
|
||||
# Add inheritance blocks of this state to the object
|
||||
for sib in StateInheritanceBlock.objects.filter(state=state):
|
||||
permissions.utils.add_inheritance_block(obj, sib.permission)
|
Loading…
Reference in a new issue