Support allowed() in workflows.Step

There are cases where we want to display workflow Step conditionally.

Change-Id: I71ae3ed270d9472190430ac5b4a34682ce3b3f29
Closes-Bug: #1683262
This commit is contained in:
Akihiro Motoki 2017-04-17 08:09:31 +00:00
parent bf1940f7b9
commit fd55569ab0
3 changed files with 44 additions and 1 deletions

View File

@ -82,6 +82,14 @@ class AdminAction(workflows.Action):
permissions = ("horizon.test",)
class TestDisabledAction(workflows.Action):
disabled_id = forms.CharField(label="Disabled")
class Meta(object):
name = "Test Action Disabled"
slug = "test_action_disabled"
class AdminForbiddenAction(workflows.Action):
admin_id = forms.CharField(label="Admin forbidden")
@ -121,6 +129,14 @@ class AdminStep(workflows.Step):
before = TestStepTwo
class TestDisabledStep(workflows.Step):
action_class = TestDisabledAction
contributes = ("disabled_id",)
def allowed(self, request):
return False
class AdminForbiddenStep(workflows.Step):
action_class = AdminForbiddenAction
@ -312,6 +328,15 @@ class WorkflowsTests(test.TestCase):
'<AdminStep: admin_action>',
'<TestStepTwo: test_action_two>'])
def test_has_allowed(self):
TestWorkflow.register(TestDisabledStep)
flow = TestWorkflow(self.request)
# Check TestDisabledStep is not included
# even though TestDisabledStep is registered.
self.assertQuerysetEqual(flow.steps,
['<TestStepOne: test_action_one>',
'<TestStepTwo: test_action_two>'])
def test_step_is_hidden_on_policy(self):
self.policy_patcher.stop()

View File

@ -465,6 +465,16 @@ class Step(object):
"""Returns True if action contains any required fields."""
return any(field.required for field in self.action.fields.values())
def allowed(self, request):
"""Determines whether or not the step is displayed.
Step instances can override this method to specify conditions under
which this tab should not be shown at all by returning ``False``.
The default behavior is to return ``True`` for all cases.
"""
return True
class WorkflowMetaclass(type):
def __new__(mcs, name, bases, attrs):
@ -694,7 +704,8 @@ class Workflow(html.HTMLElement):
for step_class in ordered_step_classes:
cls = self._registry[step_class]
if (has_permissions(self.request.user, cls) and
policy.check(cls.policy_rules, self.request)):
policy.check(cls.policy_rules, self.request) and
cls.allowed(self.request)):
self._ordered_steps.append(cls)
def _order_steps(self):

View File

@ -0,0 +1,7 @@
---
features:
- Horizon workflow Step now support allowed() method to determine
the step should be displayed conditionally.
The workflow Step class already support policy check and permission
mechanism to decide the step should be displayed, but allowed() is used
to support more complex or dynamic condition.