]> git.ipfire.org Git - thirdparty/patchwork.git/commitdiff
REST: Add 'actor' field to '/events' model
authorJohan Herland <johan@herland.net>
Sun, 1 Dec 2019 01:49:54 +0000 (02:49 +0100)
committerStephen Finucane <stephen@that.guru>
Sun, 1 Dec 2019 11:59:37 +0000 (11:59 +0000)
Signed-off-by: Johan Herland <johan@herland.net>
Reviewed-by: Stephen Finucane <stephen@that.guru>
Acked-by: Daniel Axtens <dja@axtens.net>
Cc: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
Closes: #73
docs/api/schemas/latest/patchwork.yaml
docs/api/schemas/patchwork.j2
docs/api/schemas/v1.2/patchwork.yaml
docs/usage/overview.rst
patchwork/api/event.py
patchwork/api/filters.py
patchwork/tests/api/test_event.py

index 6c7564baf81be2e5c08589516c66acc119b6a2ef..fc23cdb030785bf3f84b65b763f4f6dfe33fa4f3 100644 (file)
@@ -1649,6 +1649,13 @@ components:
           type: string
           format: iso8601
           readOnly: true
+        actor:
+          type: object
+          title: Actor
+          description: The user that caused/created this event.
+          readOnly: true
+          allOf:
+            - $ref: '#/components/schemas/UserEmbedded'
         payload:
           type: object
     EventCoverCreated:
index e2c8a8c1000e81cb8293417bc861549ba90f2d21..85f3977ca15c9e083316f81cb05358244d173f8e 100644 (file)
@@ -1679,6 +1679,15 @@ components:
           type: string
           format: iso8601
           readOnly: true
+{% if version >= (1, 2) %}
+        actor:
+          type: object
+          title: Actor
+          description: The user that caused/created this event.
+          readOnly: true
+          allOf:
+            - $ref: '#/components/schemas/UserEmbedded'
+{% endif %}
         payload:
           type: object
     EventCoverCreated:
index 7dc95793faa333bc57ebaccb4dca94f671fea779..b4d1cf689009a3aa431bf97c5be95f57c3a6abfe 100644 (file)
@@ -1649,6 +1649,13 @@ components:
           type: string
           format: iso8601
           readOnly: true
+        actor:
+          type: object
+          title: Actor
+          description: The user that caused/created this event.
+          readOnly: true
+          allOf:
+            - $ref: '#/components/schemas/UserEmbedded'
         payload:
           type: object
     EventCoverCreated:
index e84e13d91d9c38e2769aab44371a4000c76296cc..273c792a72786f1fb93d4c8e2a4d3214ad2ed42b 100644 (file)
@@ -228,6 +228,9 @@ properties:
 ``date``
   When this event was created
 
+``actor``
+  The user, if any, that caused/created this event
+
 ``payload``
   Additional information
 
index e6d467d11c3d8b583ced724717197686369110fb..e00ce051ad7aa50612adfa1a32c7605ab41b5046 100644 (file)
@@ -23,6 +23,7 @@ from patchwork.models import Event
 class EventSerializer(ModelSerializer):
 
     project = ProjectSerializer(read_only=True)
+    actor = UserSerializer()
     patch = PatchSerializer(read_only=True)
     series = SeriesSerializer(read_only=True)
     cover = CoverLetterSerializer(read_only=True)
@@ -50,7 +51,7 @@ class EventSerializer(ModelSerializer):
         data = super(EventSerializer, self).to_representation(instance)
         payload = OrderedDict()
         kept_fields = self._category_map[instance.category] + [
-            'id', 'category', 'project', 'date']
+            'id', 'category', 'project', 'date', 'actor']
 
         for field in [x for x in data]:
             if field not in kept_fields:
@@ -65,10 +66,13 @@ class EventSerializer(ModelSerializer):
 
     class Meta:
         model = Event
-        fields = ('id', 'category', 'project', 'date', 'patch', 'series',
-                  'cover', 'previous_state', 'current_state',
+        fields = ('id', 'category', 'project', 'date', 'actor', 'patch',
+                  'series', 'cover', 'previous_state', 'current_state',
                   'previous_delegate', 'current_delegate', 'created_check')
         read_only_fields = fields
+        versioned_fields = {
+            '1.2': ('actor', ),
+        }
 
 
 class EventList(ListAPIView):
index 6b4d84c7c22c32f4fde6cb3ddbe11821e37be3af..60f1a3634fcf0be68199863470da59d952223e8c 100644 (file)
@@ -236,7 +236,10 @@ class EventFilterSet(TimestampMixin, BaseFilterSet):
 
     class Meta:
         model = Event
-        fields = ('project', 'category', 'series', 'patch', 'cover')
+        fields = ('project', 'category', 'series', 'patch', 'cover', 'actor')
+        versioned_fields = {
+            '1.2': ('actor', ),
+        }
 
 
 class BundleFilterSet(BaseFilterSet):
index bff8f404078b4219dbe92568a90e96cf55b6b8d5..c202a650b92279cf8d299e39e07e46ea22e86563 100644 (file)
@@ -35,11 +35,16 @@ class TestEventAPI(utils.APITestCase):
     def assertSerialized(self, event_obj, event_json):
         self.assertEqual(event_obj.id, event_json['id'])
         self.assertEqual(event_obj.category, event_json['category'])
+        if event_obj.actor is None:
+            self.assertIsNone(event_json['actor'])
 
         # nested fields
 
         self.assertEqual(event_obj.project.id,
                          event_json['project']['id'])
+        if event_obj.actor is not None:
+            self.assertEqual(event_obj.actor.id,
+                             event_json['actor']['id'])
 
         # TODO(stephenfin): Check other fields
 
@@ -66,10 +71,12 @@ class TestEventAPI(utils.APITestCase):
         # check-created
         create_check(patch=patch)
         # patch-delegated, patch-state-changed
+        actor = create_maintainer(project=patch.project)
         user = create_maintainer(project=patch.project)
         state = create_state()
         patch.delegate = user
         patch.state = state
+        self.assertTrue(patch.is_editable(actor))
         patch.save()
 
         return Event.objects.all()
@@ -149,6 +156,28 @@ class TestEventAPI(utils.APITestCase):
         resp = self.client.get(self.api_url(), {'series': 999999})
         self.assertEqual(0, len(resp.data))
 
+    def test_list_filter_actor(self):
+        """Filter events by actor."""
+        events = self._create_events()
+
+        # The final two events (patch-delegated, patch-state-changed)
+        # have an actor set
+        actor = events[0].actor
+        resp = self.client.get(self.api_url(), {'actor': actor.pk})
+        self.assertEqual(2, len(resp.data))
+
+        resp = self.client.get(self.api_url(), {'actor': 'foo-bar'})
+        self.assertEqual(0, len(resp.data))
+
+    def test_list_filter_actor_version_1_1(self):
+        """Filter events by actor using API v1.1."""
+        events = self._create_events()
+
+        # we still see all the events since the actor field is ignored
+        resp = self.client.get(self.api_url(version='1.1'),
+                               {'actor': 'foo-bar'})
+        self.assertEqual(len(events), len(resp.data))
+
     def test_order_by_date_default(self):
         """Assert the default ordering is by date descending."""
         self._create_events()