From de36300a2f78c7d22e9f6879342b99ad1c4586b2 Mon Sep 17 00:00:00 2001 From: Johan Herland Date: Sun, 1 Dec 2019 02:49:54 +0100 Subject: REST: Add 'actor' field to '/events' model Signed-off-by: Johan Herland Reviewed-by: Stephen Finucane Acked-by: Daniel Axtens Cc: Mauro Carvalho Chehab Closes: #73 --- docs/api/schemas/latest/patchwork.yaml | 7 +++++++ docs/api/schemas/patchwork.j2 | 9 +++++++++ docs/api/schemas/v1.2/patchwork.yaml | 7 +++++++ docs/usage/overview.rst | 3 +++ patchwork/api/event.py | 10 +++++++--- patchwork/api/filters.py | 5 ++++- patchwork/tests/api/test_event.py | 29 +++++++++++++++++++++++++++++ 7 files changed, 66 insertions(+), 4 deletions(-) diff --git a/docs/api/schemas/latest/patchwork.yaml b/docs/api/schemas/latest/patchwork.yaml index 6c7564b..fc23cdb 100644 --- a/docs/api/schemas/latest/patchwork.yaml +++ b/docs/api/schemas/latest/patchwork.yaml @@ -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: diff --git a/docs/api/schemas/patchwork.j2 b/docs/api/schemas/patchwork.j2 index e2c8a8c..85f3977 100644 --- a/docs/api/schemas/patchwork.j2 +++ b/docs/api/schemas/patchwork.j2 @@ -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: diff --git a/docs/api/schemas/v1.2/patchwork.yaml b/docs/api/schemas/v1.2/patchwork.yaml index 7dc9579..b4d1cf6 100644 --- a/docs/api/schemas/v1.2/patchwork.yaml +++ b/docs/api/schemas/v1.2/patchwork.yaml @@ -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: diff --git a/docs/usage/overview.rst b/docs/usage/overview.rst index e84e13d..273c792 100644 --- a/docs/usage/overview.rst +++ b/docs/usage/overview.rst @@ -228,6 +228,9 @@ properties: ``date`` When this event was created +``actor`` + The user, if any, that caused/created this event + ``payload`` Additional information diff --git a/patchwork/api/event.py b/patchwork/api/event.py index e6d467d..e00ce05 100644 --- a/patchwork/api/event.py +++ b/patchwork/api/event.py @@ -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): diff --git a/patchwork/api/filters.py b/patchwork/api/filters.py index 6b4d84c..60f1a36 100644 --- a/patchwork/api/filters.py +++ b/patchwork/api/filters.py @@ -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): diff --git a/patchwork/tests/api/test_event.py b/patchwork/tests/api/test_event.py index bff8f40..c202a65 100644 --- a/patchwork/tests/api/test_event.py +++ b/patchwork/tests/api/test_event.py @@ -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() -- cgit v1.2.3