[PATCH 3/3] REST: Allow a project to restrict submitter state changes
Daniel Axtens
dja at axtens.net
Tue Aug 3 01:27:29 AEST 2021
As with xmlrpc and the UI.
Signed-off-by: Daniel Axtens <dja at axtens.net>
---
patchwork/api/patch.py | 10 +++++
patchwork/tests/api/test_patch.py | 70 +++++++++++++++++++++++++++++++
2 files changed, 80 insertions(+)
diff --git a/patchwork/api/patch.py b/patchwork/api/patch.py
index 9d222754412e..b8d0d5e17749 100644
--- a/patchwork/api/patch.py
+++ b/patchwork/api/patch.py
@@ -122,6 +122,16 @@ class PatchListSerializer(BaseHyperlinkedModelSerializer):
"'%s'" % (value, self.instance.project))
return value
+ def validate_state(self, value):
+ """Check that the users is authorised to set this state."""
+ user = self.context.get('request').user
+ if not self.instance.can_set_state(user):
+ raise ValidationError(
+ "User '%s' is not permitted to set state '%s' on this patch." %
+ (user, value.name))
+
+ return value
+
def to_representation(self, instance):
# NOTE(stephenfin): This is here to ensure our API looks the same even
# after we changed the series-patch relationship from M:N to 1:N. It
diff --git a/patchwork/tests/api/test_patch.py b/patchwork/tests/api/test_patch.py
index da2dd6e9084b..9de7b0d105f4 100644
--- a/patchwork/tests/api/test_patch.py
+++ b/patchwork/tests/api/test_patch.py
@@ -11,6 +11,9 @@ from django.conf import settings
from django.urls import reverse
from patchwork.models import Patch
+from patchwork.models import Person
+from patchwork.models import Project
+from patchwork.models import State
from patchwork.tests.api import utils
from patchwork.tests.utils import create_maintainer
from patchwork.tests.utils import create_patch
@@ -409,3 +412,70 @@ class TestPatchAPI(utils.APITestCase):
self.client.force_authenticate(user=user)
resp = self.client.delete(self.api_url(patch.id))
self.assertEqual(status.HTTP_405_METHOD_NOT_ALLOWED, resp.status_code)
+
+
+ at unittest.skipUnless(settings.ENABLE_REST_API, 'requires ENABLE_REST_API')
+class TestPatchStateChecks(utils.APITestCase):
+ fixtures = ['default_tags']
+
+ @staticmethod
+ def api_url(item=None):
+ kwargs = {'pk': item}
+ return reverse('api-patch-detail', kwargs=kwargs)
+
+ def setUp(self):
+ self.projects = {}
+ self.maintainers = {}
+ self.delegates = {}
+ self.submitters = {}
+ self.patches = {}
+
+ for project_type in (Project.SUBMITTER_NO_STATE_CHANGES,
+ Project.SUBMITTER_ALL_STATE_CHANGES):
+ project = create_project(
+ submitter_state_change_rules=project_type)
+ self.projects[project_type] = project
+ self.maintainers[project_type] = create_maintainer(project)
+ submitter = create_user(project)
+ self.submitters[project_type] = submitter
+ delegate = create_user(project)
+ self.delegates[project_type] = delegate
+
+ patch = create_patch(project=project,
+ submitter=Person.objects.get(
+ user=submitter),
+ delegate=delegate)
+ self.patches[project_type] = patch
+
+ create_state(name="New")
+ create_state(name="RFC")
+
+ def can_set_state(self, patch, user):
+ new_state = State.objects.get(name="New")
+ rfc_state = State.objects.get(name="RFC")
+ patch.state = new_state
+ patch.save()
+
+ self.client.force_authenticate(user=user)
+ resp = self.client.patch(self.api_url(patch.id),
+ {'state': rfc_state.slug})
+
+ if resp.status_code != status.HTTP_200_OK:
+ return False
+
+ self.assertEqual(Patch.objects.get(id=patch.id).state, rfc_state)
+ return True
+
+ def test_allset(self):
+ project = Project.SUBMITTER_ALL_STATE_CHANGES
+ patch = self.patches[project]
+ self.assertTrue(self.can_set_state(patch, self.maintainers[project]))
+ self.assertTrue(self.can_set_state(patch, self.delegates[project]))
+ self.assertTrue(self.can_set_state(patch, self.submitters[project]))
+
+ def test_noset(self):
+ project = Project.SUBMITTER_NO_STATE_CHANGES
+ patch = self.patches[project]
+ self.assertTrue(self.can_set_state(patch, self.maintainers[project]))
+ self.assertTrue(self.can_set_state(patch, self.delegates[project]))
+ self.assertFalse(self.can_set_state(patch, self.submitters[project]))
--
2.30.2
More information about the Patchwork
mailing list