diff --git a/taiga/projects/occ/mixins.py b/taiga/projects/occ/mixins.py index 27b8e78a..777a59b4 100644 --- a/taiga/projects/occ/mixins.py +++ b/taiga/projects/occ/mixins.py @@ -37,7 +37,9 @@ class OCCResourceMixin(object): return param_version def _validate_param_version(self, param_version, current_version): - if param_version is not None: + if param_version is None: + return False + else: if param_version < 0: return False if current_version is not None and param_version > current_version: @@ -50,28 +52,27 @@ class OCCResourceMixin(object): if obj.id: current_version = type(obj).objects.model.objects.get(id=obj.id).version - # Extract param version - param_version = self._extract_param_version() - if not self._validate_param_version(param_version, current_version): - raise exc.WrongArguments({"version": _("The version is not valid")}) + # Extract param version + param_version = self._extract_param_version() + if not self._validate_param_version(param_version, current_version): + raise exc.WrongArguments({"version": _("The version parameter is not valid")}) - if current_version != param_version: - diff_versions = current_version - param_version + if current_version != param_version: + diff_versions = current_version - param_version - modifying_fields = set(self.request.DATA.keys()) - if "version" in modifying_fields: - modifying_fields.remove("version") + modifying_fields = set(self.request.DATA.keys()) + if "version" in modifying_fields: + modifying_fields.remove("version") - modified_fields = set(get_modified_fields(obj, diff_versions)) - if "version" in modifying_fields: - modified_fields.remove("version") + modified_fields = set(get_modified_fields(obj, diff_versions)) + if "version" in modifying_fields: + modified_fields.remove("version") - both_modified = modifying_fields & modified_fields + both_modified = modifying_fields & modified_fields - if both_modified: - raise exc.WrongArguments({"version": _("The version doesn't match with the current one")}) + if both_modified: + raise exc.WrongArguments({"version": _("The version doesn't match with the current one")}) - if obj.id: obj.version = models.F('version') + 1 def pre_save(self, obj): diff --git a/tests/integration/test_occ.py b/tests/integration/test_occ.py index 0e6eb974..9826cf0e 100644 --- a/tests/integration/test_occ.py +++ b/tests/integration/test_occ.py @@ -333,3 +333,26 @@ def test_valid_concurrent_save_for_task_different_fields(client): data = {"version": 1, "description": "test 2"} response = client.patch(url, json.dumps(data), content_type="application/json") assert response.status_code == 200 + + + +def test_invalid_save_without_version_parameter(client): + user = f.UserFactory.create() + project = f.ProjectFactory.create(owner=user) + f.MembershipFactory.create(project=project, user=user, is_owner=True) + client.login(user) + + mock_path = "taiga.projects.tasks.api.TaskViewSet.pre_conditions_on_save" + with patch(mock_path): + url = reverse("tasks-list") + data = {"subject": "test", + "project": project.id, + "status": f.TaskStatusFactory.create(project=project).id} + response = client.json.post(url, json.dumps(data)) + assert response.status_code == 201 + + task_id = json.loads(response.content)["id"] + url = reverse("tasks-detail", args=(task_id,)) + data = {"subject": "test 1"} + response = client.patch(url, json.dumps(data), content_type="application/json") + assert response.status_code == 400