[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