[Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)

Shubham Jain posted 1 patch 5 years, 11 months ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/patchew-ci tags/patchew/20180515120228.47478-1-shubhamjain7495@gmail.com
api/rest.py                                    |  25 +++++++++++++++----
api/urls.py                                    |   3 ++-
tests/data/0023-multiple-project-patch.mbox.gz | Bin 0 -> 2274 bytes
tests/data/0024-multiple-project-patch.json.gz | Bin 0 -> 2471 bytes
tests/test_rest.py                             |  32 ++++++++++++++++++++++++-
5 files changed, 54 insertions(+), 6 deletions(-)
create mode 100644 tests/data/0023-multiple-project-patch.mbox.gz
create mode 100644 tests/data/0024-multiple-project-patch.json.gz
[Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)
Posted by Shubham Jain 5 years, 11 months ago
To apply a single message to the project according to the group user is from. For importer user, message is added to all recognised project. For other users, message is added to all the projects recognised and maintained by the user.
---
 api/rest.py                                    |  25 +++++++++++++++----
 api/urls.py                                    |   3 ++-
 tests/data/0023-multiple-project-patch.mbox.gz | Bin 0 -> 2274 bytes
 tests/data/0024-multiple-project-patch.json.gz | Bin 0 -> 2471 bytes
 tests/test_rest.py                             |  32 ++++++++++++++++++++++++-
 5 files changed, 54 insertions(+), 6 deletions(-)
 create mode 100644 tests/data/0023-multiple-project-patch.mbox.gz
 create mode 100644 tests/data/0024-multiple-project-patch.json.gz

diff --git a/api/rest.py b/api/rest.py
index 1f81fe7..94b3162 100644
--- a/api/rest.py
+++ b/api/rest.py
@@ -17,7 +17,7 @@ from mod import dispatch_module_hook
 from .models import Project, Message
 from .search import SearchEngine
 from rest_framework import (permissions, serializers, viewsets, filters,
-    mixins, generics, renderers)
+    mixins, generics, renderers, status)
 from rest_framework.decorators import detail_route
 from rest_framework.fields import SerializerMethodField, CharField, JSONField, EmailField
 from rest_framework.relations import HyperlinkedIdentityField
@@ -162,7 +162,6 @@ class AddressSerializer(serializers.Serializer):
         except:
             return [validated_data['address'], validated_data['address']]
 
-
 class BaseMessageSerializer(serializers.ModelSerializer):
     class Meta:
         model = Message
@@ -175,6 +174,9 @@ class BaseMessageSerializer(serializers.ModelSerializer):
     def create(self, validated_data):
         validated_data['recipients'] = self.fields['recipients'].create(validated_data['recipients'])
         validated_data['sender'] = self.fields['sender'].create(validated_data['sender'])
+        if 'project' in validated_data:
+            project = validated_data.pop('project')
+            return Message.objects.create(project=project, **validated_data)
         return Message.objects.create(project=self.context['project'], **validated_data)
 
 # a message_id is *not* unique, so we can only list
@@ -288,7 +290,6 @@ class SeriesViewSet(BaseMessageViewSet):
     filter_backends = (PatchewSearchFilter,)
     search_fields = (SEARCH_PARAM,)
 
-
 class ProjectSeriesViewSet(ProjectMessagesViewSetMixin,
                            SeriesViewSet, mixins.DestroyModelMixin):
     def collect_patches(self, series):
@@ -368,7 +369,7 @@ class MessagePlainTextParser(BaseParser):
         data = stream.read().decode("utf-8")
         return MboxMessage(data).get_json()
 
-class MessagesViewSet(ProjectMessagesViewSetMixin,
+class ProjectMessagesViewSet(ProjectMessagesViewSetMixin,
                       BaseMessageViewSet, mixins.CreateModelMixin):
     serializer_class = MessageSerializer
     parser_classes = (JSONParser, MessagePlainTextParser, )
@@ -388,6 +389,22 @@ class MessagesViewSet(ProjectMessagesViewSetMixin,
                                            context=self.get_serializer_context())
         return self.get_paginated_response(serializer.data)
 
+class MessagesViewSet(BaseMessageViewSet):
+    serializer_class = MessageSerializer
+    parser_classes = (JSONParser, MessagePlainTextParser, )
+    
+    def create(self, request, *args, **kwargs):
+        projects = [p for p in Project.objects.all() if p.recognizes(MboxMessage(self.request.data['mbox']))]
+        if 'importers' not in self.request.user.groups.all():
+            projects = set(projects) & set([p for p in Project.objects.all() if p.maintained_by(self.request.user)])
+        results = []
+        for project in projects:
+            serializer = self.get_serializer(data=request.data)
+            serializer.is_valid(raise_exception=True)
+            serializer.save(project=project)
+            results.append(serializer.data)
+        return Response(OrderedDict([('count', len(results)),('results', results)]), status=status.HTTP_201_CREATED)
+
 # Results
 
 class HyperlinkedResultField(HyperlinkedIdentityField):
diff --git a/api/urls.py b/api/urls.py
index 64e9629..2fd4e0f 100644
--- a/api/urls.py
+++ b/api/urls.py
@@ -31,12 +31,13 @@ router.include_format_suffixes = False
 router.register('users', rest.UsersViewSet)
 router.register('projects', rest.ProjectsViewSet)
 router.register('series', rest.SeriesViewSet, base_name='series')
+router.register('messages', rest.MessagesViewSet)
 
 projects_router = NestedDefaultRouter(router, 'projects', lookup='projects', trailing_slash=True)
 projects_router.include_format_suffixes = False
 projects_router.register('results', rest.ProjectResultsViewSet, base_name='results')
 projects_router.register('series', rest.ProjectSeriesViewSet, base_name='series')
-projects_router.register('messages', rest.MessagesViewSet, base_name='messages')
+projects_router.register('messages', rest.ProjectMessagesViewSet, base_name='messages')
 
 results_router = NestedDefaultRouter(projects_router, 'series', lookup='series', trailing_slash=True)
 results_router.include_format_suffixes = False
diff --git a/tests/data/0023-multiple-project-patch.mbox.gz b/tests/data/0023-multiple-project-patch.mbox.gz
new file mode 100644
index 0000000000000000000000000000000000000000..6d63736020c35a523cdef327a3022c759c941436
GIT binary patch
literal 2274
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

literal 0
HcmV?d00001

diff --git a/tests/data/0024-multiple-project-patch.json.gz b/tests/data/0024-multiple-project-patch.json.gz
new file mode 100644
index 0000000000000000000000000000000000000000..2866b7fbac5a2fc5607b723dbd3d125a7dca4b7c
GIT binary patch
literal 2471
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

literal 0
HcmV?d00001

diff --git a/tests/test_rest.py b/tests/test_rest.py
index 7896e8a..2da5459 100755
--- a/tests/test_rest.py
+++ b/tests/test_rest.py
@@ -37,6 +37,8 @@ class RestTest(PatchewTestCase):
         self.sp.prefix_tags = "block"
         self.sp.save()
         self.SUBPROJECT_BASE = '%sprojects/%d/' % (self.REST_BASE, self.sp.id)
+        self.p2 = self.add_project("EDK 2", "edk2-devel@lists.01.org")
+        self.PROJECT_BASE_2 = '%sprojects/%d/' % (self.REST_BASE, self.p2.id)
 
         self.admin = User.objects.get(username='admin')
         self.USER_BASE = '%susers/%d/' % (self.REST_BASE, self.admin.id)
@@ -64,7 +66,7 @@ class RestTest(PatchewTestCase):
 
     def test_projects(self):
         resp = self.api_client.get(self.REST_BASE + 'projects/')
-        self.assertEquals(resp.data['count'], 2)
+        self.assertEquals(resp.data['count'], 3)
         self.assertEquals(resp.data['results'][0]['resource_uri'], self.PROJECT_BASE)
         self.assertEquals(resp.data['results'][0]['name'], "QEMU")
         self.assertEquals(resp.data['results'][0]['mailing_list'], "qemu-devel@nongnu.org")
@@ -295,6 +297,34 @@ class RestTest(PatchewTestCase):
         self.assertEqual(resp_get.status_code, 200)
         self.assertEqual(resp.data['subject'], "[Qemu-devel] [PATCH v4 0/2] Report format specific info for LUKS block driver")
 
+    def test_create_message_without_project_pk(self):
+        dp = self.get_data_path("0024-multiple-project-patch.json.gz")
+        with open(dp, "r") as f:
+            data = f.read()
+        self.api_client.login(username=self.user, password=self.password)
+        resp = self.api_client.post(self.REST_BASE + "messages/", data, content_type='application/json')
+        self.assertEqual(resp.status_code, 201)
+        self.assertEqual(resp.data['count'], 2)
+        resp_get = self.api_client.get(self.PROJECT_BASE + "messages/20180223132311.26555-2-marcandre.lureau@redhat.com/")
+        self.assertEqual(resp_get.status_code, 200)
+        self.assertEqual(resp_get.data['subject'], "[Qemu-devel] [PATCH 1/7] SecurityPkg/Tcg2Pei: drop Tcg2PhysicalPresenceLib dependency")
+        resp_get2 = self.api_client.get(self.PROJECT_BASE_2 + "messages/20180223132311.26555-2-marcandre.lureau@redhat.com/")
+        self.assertEqual(resp_get2.status_code, 200)
+
+    def test_create_text_message_without_project_pk(self):
+        dp = self.get_data_path("0023-multiple-project-patch.mbox.gz")
+        with open(dp, "r") as f:
+            data = f.read()
+        self.api_client.login(username=self.user, password=self.password)
+        resp = self.api_client.post(self.REST_BASE + "messages/", data, content_type='message/rfc822')
+        self.assertEqual(resp.status_code, 201)
+        self.assertEqual(resp.data['count'], 2)
+        resp_get = self.api_client.get(self.PROJECT_BASE + "messages/20180223132311.26555-2-marcandre.lureau@redhat.com/")
+        self.assertEqual(resp_get.status_code, 200)
+        self.assertEqual(resp_get.data['subject'], "[Qemu-devel] [PATCH 1/7] SecurityPkg/Tcg2Pei: drop Tcg2PhysicalPresenceLib dependency")
+        resp_get2 = self.api_client.get(self.PROJECT_BASE_2 + "messages/20180223132311.26555-2-marcandre.lureau@redhat.com/")
+        self.assertEqual(resp_get2.status_code, 200)
+
     def test_message(self):
         series = self.apply_and_retrieve('0001-simple-patch.mbox.gz',
                                          self.p.id, '20160628014747.20971-1-famz@redhat.com')
-- 
2.14.3 (Apple Git-98)

_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Re: [Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)
Posted by Paolo Bonzini 5 years, 11 months ago
On 15/05/2018 14:02, Shubham Jain wrote:
> +    def create(self, request, *args, **kwargs):
> +        projects = [p for p in Project.objects.all() if p.recognizes(MboxMessage(self.request.data['mbox']))]
> +        if 'importers' not in self.request.user.groups.all():
> +            projects = set(projects) & set([p for p in Project.objects.all() if p.maintained_by(self.request.user)])

This can be just "projects = (p for p in projects if
p.maintained_by(self.request_user))".  I'll make the change and commit it.

Fam, what do you think should Admin accounts do?  Import only to the
projects they maintain, or to all of them?

Thanks,

Paolo

_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Re: [Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)
Posted by Shubham Jain 5 years, 11 months ago
>
> This can be just "projects = (p for p in projects if
> p.maintained_by(self.request_user))".  I'll make the change and commit it.
>
> What's next?
_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Re: [Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)
Posted by Paolo Bonzini 5 years, 11 months ago
On 15/05/2018 14:40, Shubham Jain wrote:
>     This can be just "projects = (p for p in projects if
>     p.maintained_by(self.request_user))".  I'll make the change and
>     commit it.
> 
> What's next? 

Write more tests. :)

Then I'm thinking of jumping directly to OAuth...  Either that, or the
update-project-head old-style request, which would be an easy POST
request like /projects/{pk}/update-head.

Another possibility is to start modifying the patchew-cli tool to use
the REST requests when applicable.  In fact, doing that for
update-project-head is probably the best way to test your new code,
because tests only use (by test_project_update in test_import.py) it via
patchew-cli.

Thanks,

Paolo

_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Re: [Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)
Posted by Shubham Jain 5 years, 11 months ago
On Tue, May 15, 2018 at 6:25 PM Paolo Bonzini <pbonzini@redhat.com> wrote:

> On 15/05/2018 14:40, Shubham Jain wrote:
> >     This can be just "projects = (p for p in projects if
> >     p.maintained_by(self.request_user))".  I'll make the change and
> >     commit it.
> >
> > What's next?
>
> Write more tests. :)

Alright. Could you please elaborate "Add more testcases around
authorization: check for 403 on unauthenticated post, check what the
"importer" group is allowed to do, etc."?

>
>
Then I'm thinking of jumping directly to OAuth...  Either that, or the
> update-project-head old-style request, which would be an easy POST
> request like /projects/{pk}/update-head.
>
> Cool, I'll start going through the documentation of OAuth side by side.
Which third party OAuth are we going to use?

Shubham
_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Re: [Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)
Posted by Paolo Bonzini 5 years, 11 months ago
On 15/05/2018 15:27, Shubham Jain wrote:
> 
> 
> On Tue, May 15, 2018 at 6:25 PM Paolo Bonzini <pbonzini@redhat.com
> <mailto:pbonzini@redhat.com>> wrote:
> 
>     On 15/05/2018 14:40, Shubham Jain wrote:
>     >     This can be just "projects = (p for p in projects if
>     >     p.maintained_by(self.request_user))".  I'll make the change and
>     >     commit it.
>     >
>     > What's next? 
> 
>     Write more tests. :)
> 
> Alright. Could you please elaborate "Add more testcases around
> authorization: check for 403 on unauthenticated post, check what the
> "importer" group is allowed to do, etc."? 

- check that POST fails if you haven't logged in

- check that the rules for importing messages work (import by
maintainer, import by non-maintainer, import by someone in the
"importer" group)

>      
> 
>     Then I'm thinking of jumping directly to OAuth...  Either that, or the
>     update-project-head old-style request, which would be an easy POST
>     request like /projects/{pk}/update-head.
> 
> Cool, I'll start going through the documentation of OAuth side by side.
> Which third party OAuth are we going to use?

I think Patchew should be an OAuth provider so that it can restrict API
access to registered clients.  There are tutorials
https://django-oauth-toolkit.readthedocs.io/en/latest/

Paolo

_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Re: [Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)
Posted by Fam Zheng 5 years, 11 months ago
On Tue, 05/15 14:08, Paolo Bonzini wrote:
> On 15/05/2018 14:02, Shubham Jain wrote:
> > +    def create(self, request, *args, **kwargs):
> > +        projects = [p for p in Project.objects.all() if p.recognizes(MboxMessage(self.request.data['mbox']))]

It is better to create MboxMessage object once to avoid repeating the mbox
parse:

             m = MboxMessage(self.request.data['mbox'])
             projects = [p for p in Project.objects.all() if p.recognizes(m)]


> > +        if 'importers' not in self.request.user.groups.all():
> > +            projects = set(projects) & set([p for p in Project.objects.all() if p.maintained_by(self.request.user)])
> 
> This can be just "projects = (p for p in projects if
> p.maintained_by(self.request_user))".  I'll make the change and commit it.
> 
> Fam, what do you think should Admin accounts do?  Import only to the
> projects they maintain, or to all of them?

I think all is better. The projects to import can be explicitly limited if they want.

Fam

_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Re: [Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)
Posted by Paolo Bonzini 5 years, 11 months ago
On 16/05/2018 03:31, Fam Zheng wrote:
> On Tue, 05/15 14:08, Paolo Bonzini wrote:
>> On 15/05/2018 14:02, Shubham Jain wrote:
>>> +    def create(self, request, *args, **kwargs):
>>> +        projects = [p for p in Project.objects.all() if p.recognizes(MboxMessage(self.request.data['mbox']))]
> 
> It is better to create MboxMessage object once to avoid repeating the mbox
> parse:
> 
>              m = MboxMessage(self.request.data['mbox'])
>              projects = [p for p in Project.objects.all() if p.recognizes(m)]

Also the MboxMessage probably should be created from self.request.data,
without doing more parsing of the mbox.

Alternatively, p.recognizes() could take an array of recipients rather
than an MboxMessage.

> 
>>> +        if 'importers' not in self.request.user.groups.all():
>>> +            projects = set(projects) & set([p for p in Project.objects.all() if p.maintained_by(self.request.user)])
>>
>> This can be just "projects = (p for p in projects if
>> p.maintained_by(self.request_user))".  I'll make the change and commit it.
>>
>> Fam, what do you think should Admin accounts do?  Import only to the
>> projects they maintain, or to all of them?
> 
> I think all is better. The projects to import can be explicitly limited if they want.

Ok, thanks!  Shubham is going to add more tests which I'm sure will
uncover some bugs, :) so let's do this change as well.

I've updated the checklist at
https://github.com/patchew-project/patchew/issues/75.

Thanks,

Paolo

_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Re: [Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)
Posted by Fam Zheng 5 years, 11 months ago
On Wed, 05/16 09:38, Paolo Bonzini wrote:
> On 16/05/2018 03:31, Fam Zheng wrote:
> > On Tue, 05/15 14:08, Paolo Bonzini wrote:
> >> On 15/05/2018 14:02, Shubham Jain wrote:
> >>> +    def create(self, request, *args, **kwargs):
> >>> +        projects = [p for p in Project.objects.all() if p.recognizes(MboxMessage(self.request.data['mbox']))]
> > 
> > It is better to create MboxMessage object once to avoid repeating the mbox
> > parse:
> > 
> >              m = MboxMessage(self.request.data['mbox'])
> >              projects = [p for p in Project.objects.all() if p.recognizes(m)]
> 
> Also the MboxMessage probably should be created from self.request.data,
> without doing more parsing of the mbox.

Not sure I understand this, is it related to your below idea? I don't see how
MboxMessage.__init__ should handle self.request.data.

> 
> Alternatively, p.recognizes() could take an array of recipients rather
> than an MboxMessage.

Yes, but remember there is also the prefix_tags conditions.

Fam

_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Re: [Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)
Posted by Paolo Bonzini 5 years, 11 months ago
On 16/05/2018 09:53, Fam Zheng wrote:
> On Wed, 05/16 09:38, Paolo Bonzini wrote:
>> On 16/05/2018 03:31, Fam Zheng wrote:
>>> On Tue, 05/15 14:08, Paolo Bonzini wrote:
>>>> On 15/05/2018 14:02, Shubham Jain wrote:
>>>>> +    def create(self, request, *args, **kwargs):
>>>>> +        projects = [p for p in Project.objects.all() if p.recognizes(MboxMessage(self.request.data['mbox']))]
>>>
>>> It is better to create MboxMessage object once to avoid repeating the mbox
>>> parse:
>>>
>>>              m = MboxMessage(self.request.data['mbox'])
>>>              projects = [p for p in Project.objects.all() if p.recognizes(m)]
>>
>> Also the MboxMessage probably should be created from self.request.data,
>> without doing more parsing of the mbox.
> 
> Not sure I understand this, is it related to your below idea? I don't see how
> MboxMessage.__init__ should handle self.request.data.

No, I mean that just like MboxMessage can do text->json, it should be
possible to create a MboxMessage from JSON input.

So you'd have:

- parsing message/rfc822 requests does the text->json conversion (using
MboxMessage, but that's an implementation detail)

- create() does json->MboxMessage and uses the MboxMessage to do
p.recognizes(m)

>> Alternatively, p.recognizes() could take an array of recipients rather
>> than an MboxMessage.
> 
> Yes, but remember there is also the prefix_tags conditions.

You're right, so we do have to go through MboxMessage.

Paolo

_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Re: [Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)
Posted by Shubham Jain 5 years, 11 months ago
- create() does json->MboxMessage and uses the MboxMessage to do
> p.recognizes(m)
>
How to create MboxMessage from json?

Also, while writing tests for authentication, I found out that
api/v1/messages/ is exposed only to importer and superuser. So if a user
who is just a maintainer of project, how will he POST/create a message?
_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel
Re: [Patchew-devel] [PATCH v2] rest: add api/v1/messages endpoint (POST support)
Posted by Paolo Bonzini 5 years, 11 months ago
On 16/05/2018 17:45, Shubham Jain wrote:
> 
> 
>     - create() does json->MboxMessage and uses the MboxMessage to do
>     p.recognizes(m)
> 
> How to create MboxMessage from json? 

By writing new code (e.g. "if isinstance(argument, dict)" in
MboxMessage's constructor). :)

But it can be sorted out later.

As agreed on IRC, the next step can be to move update-project-head's
implementation mostly out of api/views.py, so that we can add it to the
REST API.

Paolo

_______________________________________________
Patchew-devel mailing list
Patchew-devel@redhat.com
https://www.redhat.com/mailman/listinfo/patchew-devel