[Patchew-devel] [PATCH] Make Patchew cli use rest api

Shubham Jain shubhamjain7495 at gmail.com
Mon Jun 25 17:58:04 UTC 2018


Paolo, also we need to write some tests. there are no tests for
update-project-head and delete series that uses patches-cli
Thanks
Shubham

On Mon, Jun 25, 2018 at 5:43 PM Paolo Bonzini <pbonzini at redhat.com> wrote:

> On 25/06/2018 14:06, Shubham Jain wrote:
> > - Disabled CSRF authentication until OAuth authentication, since DRF
> leads to csrf error while handling sessionauthentication.
> > - Added general rest_api function to make request to apis and get
> response.
> > - Make project functions use the rest_api_do instead of api_do
>
> Thanks.
>
> CSRF cannot really be removed before we have some kind of token-based
> authentication, either TokenAuthentication or OAUTH, so this part of the
> project needs to be developed in a branch.  I still prefer not to delay
> this part because it's really telling us if the REST API works or not.
>
> Fam, how would you prefer to handle the branching?  We cannot change
> patchew-cli until patchew.org has the REST API; and I would like to have
> my "result" table patches before we branch, since they seem to be
> stable, but before that we need to test migration on patchew.org (not
> just next.patchew.org).  I can think of two strategies:
>
> 1) branch "next" now, then apply the "result" table patches to both
> master and next
>
> 2) Shubham works into a branch that is neither master nor next, and we
> apply his patches only after token-based authentication is done.
>
> What do you prefer?
>
> Thanks,
>
> Paolo
>
>
> > ---
> >  api/rest.py |  9 +++++++-
> >  patchew-cli | 69
> +++++++++++++++++++++++++++++++++++++++++++++++--------------
> >  2 files changed, 61 insertions(+), 17 deletions(-)
> >
> > diff --git a/api/rest.py b/api/rest.py
> > index 084dbbc..a584578 100644
> > --- a/api/rest.py
> > +++ b/api/rest.py
> > @@ -25,6 +25,12 @@ from rest_framework.response import Response
> >  import rest_framework
> >  from mbox import addr_db_to_rest, MboxMessage
> >  from rest_framework.parsers import JSONParser, BaseParser
> > +from rest_framework.authentication import SessionAuthentication
> > +
> > +class CsrfExemptSessionAuthentication(SessionAuthentication):
> > +
> > +    def enforce_csrf(self, request):
> > +        return  # To not perform the csrf check previously happening
> >
> >  SEARCH_PARAM = 'q'
> >
> > @@ -140,7 +146,8 @@ class ProjectsViewSet(viewsets.ModelViewSet):
> >      queryset = Project.objects.all().order_by('id')
> >      serializer_class = ProjectSerializer
> >      permission_classes = (PatchewPermission,)
> > -
> > +    authentication_classes = (CsrfExemptSessionAuthentication, )
> > +
> >      @action(methods=['post'], detail=True,
> permission_classes=[ImportPermission])
> >      def update_project_head(self, request, pk=None):
> >          """
> > diff --git a/patchew-cli b/patchew-cli
> > index 174d1e6..cd5b3fa 100755
> > --- a/patchew-cli
> > +++ b/patchew-cli
> > @@ -61,7 +61,7 @@ class SubCommand(object):
> >      help = ""
> >      want_argv = False # Whether the command accepts extra arguments
> >
> > -    def api_do(self, cmd, **data):
> > +    def api_do(self, cmd, **data):
> >          """Do server api call"""
> >          logging.debug("API call '%s':" % cmd)
> >          logging.debug("data:\n%s" % data)
> > @@ -92,6 +92,39 @@ class SubCommand(object):
> >              r = None
> >          return r
> >
> > +    def rest_api_do(self, url_cmd, request_method='get',
> content_type=None, **data):
> > +        cmd = url_cmd
> > +        logging.debug("API call '%s':" % url_cmd)
> > +        logging.debug("data:\n%s" % data)
> > +        cookie = http.cookiejar.MozillaCookieJar(COOKIE_FILENAME)
> > +        try:
> > +            cookie.load()
> > +        except IOError:
> > +            pass
> > +        except http.cookiejar.LoadError:
> > +            print("Error while loading cookie", COOKIE_FILENAME)
> > +            pass
> > +        handler = urllib.request.HTTPCookieProcessor(cookie)
> > +        opener = urllib.request.build_opener(handler)
> > +        url = self.base_url + '/api/v1/' + url_cmd + '/'
> > +        if data:
> > +            post_data = json.dumps(data)
> > +        else:
> > +            post_data = ""
> > +        req = urllib.request.Request(url, data=bytes(post_data,
> encoding="utf-8"))
> > +        if content_type is not None:
> > +            req.add_header('Content-Type', content_type)
> > +        req.get_method = lambda: request_method.upper()
> > +        resp = opener.open(req)
> > +        cookie.save(ignore_discard=True, ignore_expires=True)
> > +        respdata = resp.read()
> > +        logging.debug("Server response:\n%s" % (respdata or "<empty>"))
> > +        if respdata:
> > +            r = json.loads(respdata.decode("utf-8"))
> > +        else:
> > +            r = None
> > +        return r
> > +
> >      def do(self, args, argv):
> >          """Do command"""
> >          print("Not implemented")
> > @@ -221,11 +254,11 @@ class ProjectCommand(SubCommand):
> >          parser.add_argument("--verbose", "-v", action="store_true",
> >                              help="Show details about projects")
> >          args = parser.parse_args(argv)
> > -        r = self.api_do("get-projects")
> > +        r = self.rest_api_do(url_cmd="projects", request_method='get')
> >          if args.raw:
> >              print(json.dumps(r, indent=2, separators=",:"))
> >              return 0
> > -        for p in r:
> > +        for p in r['results']:
> >              print(p["name"])
> >              if args.verbose:
> >                  for k, v in p.items():
> > @@ -239,8 +272,8 @@ class ProjectCommand(SubCommand):
> >          parser.add_argument("name", nargs="+",
> >                              help="The name of project to show info")
> >          args = parser.parse_args(argv)
> > -        r = self.api_do("get-projects")
> > -        for p in r:
> > +        r = self.rest_api_do(url_cmd="projects", request_method='get')
> > +        for p in r['results']:
> >              if not p["name"] in args.name:
> >                  continue
> >              if len(args.name) > 1:
> > @@ -263,12 +296,15 @@ class ProjectCommand(SubCommand):
> >          parser.add_argument("--desc", "-d", default="",
> >                              help="Project short discription")
> >          args = parser.parse_args(argv)
> > -        self.api_do("add-project",
> > -                    name=args.name,
> > -                    mailing_list=args.mailing_list,
> > -                    url=args.url,
> > -                    git=args.git,
> > -                    description=args.desc)
> > +
> > +        self.rest_api_do(url_cmd="projects",
> > +                         request_method='post',
> > +                         content_type='application/json',
> > +                         name=args.name,
> > +                         mailing_list=args.mailing_list,
> > +                         url=args.url,
> > +                         git=args.git,
> > +                         description=args.desc)
> >
> >      def update_one_project(self, wd, project):
> >          logging.info("Updating project '%s'", project["name"])
> > @@ -320,16 +356,17 @@ class ProjectCommand(SubCommand):
> >              except Exception as e:
> >                  logging.warn("Failed to push the new head to patchew
> mirror: %s",
> >                               str(e))
> > -        self.api_do("update-project-head", project=project["name"],
> > -                                           old_head=old_head,
> > -                                           new_head=new_head,
> > -                                           message_ids=msgids)
> > +        url = "project/" + project.id + "/update_project_head/"
> > +        self.rest_api_do("project-head",old_head=old_head,
> > +                                        new_head=new_head,
> > +                                        message_ids=msgids)
> >
> >      def update_project(self, argv):
> >          parser = argparse.ArgumentParser()
> >          parser.add_argument("--name", "-n", help="Name of the project")
> >          args = parser.parse_args(argv)
> > -        projects = self.api_do("get-projects", name=args.name)
> > +        projects = self.rest_api_do("projects")
> > +        projects = [p for p in projects['results'] if p['name'] ==
> args.name]
> >          wd = tempfile.mkdtemp()
> >          logging.debug("TMPDIR: %s", wd)
> >          try:
> >
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/patchew-devel/attachments/20180625/a9293871/attachment.htm>


More information about the Patchew-devel mailing list