diff --git a/HISTORY.rst b/HISTORY.rst index 8705dee8e1..9cc9ca28e0 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -30,6 +30,8 @@ * Fix index list API view. Add index create, delete, detail API tests. GitLab issue #564. Thanks to the Stéphane (@shoyu) for the report and debug information. +* Validate the state completion value before saving. Thanks to Manoel Brunnen + (@mbru) for the report and debug information. GitLab issue #557. 3.1.9 (2018-11-01) ================== diff --git a/docs/releases/3.1.10.rst b/docs/releases/3.1.10.rst index 0020a9a5a5..1b23b40c4d 100644 --- a/docs/releases/3.1.10.rst +++ b/docs/releases/3.1.10.rst @@ -156,6 +156,7 @@ Backward incompatible changes Bugs fixed or issues closed --------------------------- +* :gitlab-issue:`557` Break workflows with invalid input * :gitlab-issue:`559` IndexTestCase.test_dual_level_dual_document_index failure * :gitlab-issue:`562` events.links.link_user_notifications_list should use reverse diff --git a/mayan/apps/document_states/models.py b/mayan/apps/document_states/models.py index e64979c6c8..d553c7201d 100644 --- a/mayan/apps/document_states/models.py +++ b/mayan/apps/document_states/models.py @@ -208,6 +208,19 @@ class WorkflowState(models.Model): ).distinct() def save(self, *args, **kwargs): + # Solve issue #557 "Break workflows with invalid input" + # without using a migration. + # Remove blank=True, remove this, and create a migration in the next + # minor version. + + try: + self.completion = int(self.completion) + except (TypeError, ValueError): + self.completion = 0 + + #if not self.completion: + # self.completion = 0 + if self.initial: self.workflow.states.all().update(initial=False) return super(WorkflowState, self).save(*args, **kwargs) diff --git a/mayan/apps/document_states/tests/test_views.py b/mayan/apps/document_states/tests/test_views.py index 45f31aaadf..3537a4f3a2 100644 --- a/mayan/apps/document_states/tests/test_views.py +++ b/mayan/apps/document_states/tests/test_views.py @@ -135,13 +135,17 @@ class DocumentStateStateViewTestCase(WorkflowTestMixin, GenericViewTestCase): super(DocumentStateStateViewTestCase, self).setUp() self.login_user() - def _request_workflow_state_create_view(self): + def _request_workflow_state_create_view(self, extra_data=None): + data = { + 'label': TEST_WORKFLOW_STATE_LABEL, + 'completion': TEST_WORKFLOW_STATE_COMPLETION, + } + if extra_data: + data.update(extra_data) + return self.post( viewname='document_states:setup_workflow_state_create', - args=(self.workflow.pk,), data={ - 'label': TEST_WORKFLOW_STATE_LABEL, - 'completion': TEST_WORKFLOW_STATE_COMPLETION, - } + args=(self.workflow.pk,), data=data ) def test_create_workflow_state_no_access(self): @@ -164,6 +168,23 @@ class DocumentStateStateViewTestCase(WorkflowTestMixin, GenericViewTestCase): TEST_WORKFLOW_STATE_COMPLETION ) + def test_create_workflow_state_invalid_completion_with_access(self): + self._create_workflow() + + self.grant_access(obj=self.workflow, permission=permission_workflow_edit) + + response = self._request_workflow_state_create_view( + extra_data={'completion': ''} + ) + self.assertEquals(response.status_code, 302) + self.assertEquals(WorkflowState.objects.count(), 1) + self.assertEquals( + WorkflowState.objects.all()[0].label, TEST_WORKFLOW_STATE_LABEL + ) + self.assertEquals( + WorkflowState.objects.all()[0].completion, 0 + ) + def _request_workflow_state_delete_view(self): return self.post( viewname='document_states:setup_workflow_state_delete',