Skip to content

Commit

Permalink
xmlrpc: Override the request saved by the threadlocal middleware
Browse files Browse the repository at this point in the history
The auth mechanism of the XML-RPC view doesn't interact like the session
middleware: By the time the request hit the threadlocal middleware
request.user isn't populated.

So, we override the threadlocal request (and thus request.user) as soon
as we authenticate the user.

As always, if a bug manage to slip through the cracks, the punishment is
to write a test that covers it.

Fixes: #168
Signed-off-by: Damien Lespiau <damien.lespiau@intel.com>
  • Loading branch information
Damien Lespiau committed Mar 15, 2016
1 parent 43d7e27 commit 532baa9
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
30 changes: 27 additions & 3 deletions patchwork/tests/test_xmlrpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,16 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

import unittest
import urlparse

from django.conf import settings
from django.core.urlresolvers import reverse
from django.test import LiveServerTestCase
from django.utils.six.moves import xmlrpc_client

from patchwork.models import Patch
from patchwork.tests.utils import defaults
from patchwork.models import Patch, State, EventLog
from patchwork.tests.test_user import TestUser
from patchwork.tests.utils import defaults, TestSeries


@unittest.skipUnless(settings.ENABLE_XMLRPC,
Expand All @@ -45,7 +47,12 @@ def _insert_patch(self):
def setUp(self):
defaults.project.save()
defaults.patch_author_person.save()
self.url = (self.live_server_url +
self.maintainer = TestUser(username='maintainer')
self.maintainer.add_to_maintainers(defaults.project)

p = urlparse.urlparse(self.live_server_url)
self.url = (p.scheme + '://' + self.maintainer.username + ':' +
self.maintainer.password + '@' + p.netloc + p.path +
reverse('patchwork.views.xmlrpc.xmlrpc'))
self.rpc = xmlrpc_client.Server(self.url)

Expand All @@ -61,3 +68,20 @@ def testList(self):
patches = self.rpc.patch_list()
self.assertEqual(len(patches), 1)
self.assertEqual(patches[0]['id'], patch.id)

def testSetPatchState(self):
series = TestSeries(1, has_cover_letter=False)
series.insert()
patch = Patch.objects.all()[0]

superseded = State.objects.get(name='Superseded')
self.rpc.patch_set(patch.pk, {'state': superseded.pk})
patch = Patch.objects.get(pk=patch.pk)
self.assertEqual(patch.state, superseded)

# make sure we've logged the correct user with the change event
self.assertEqual(Patch.objects.count(), 1)
events = EventLog.objects.filter(event_id=2)
self.assertEqual(events.count(), 1)
event = events[0]
self.assertEquals(event.user, self.maintainer.user)
5 changes: 5 additions & 0 deletions patchwork/views/xmlrpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
from django.utils.six.moves.xmlrpc_server import SimpleXMLRPCDispatcher

from patchwork.models import Patch, Project, Person, State
from patchwork.threadlocalrequest import ThreadLocalRequestMiddleware
from patchwork.views import patch_to_mbox


Expand All @@ -64,6 +65,8 @@ def _dumps(obj, *args, **kwargs):
# map of name => (auth, func)
self.func_map = {}

self.threadlocal = ThreadLocalRequestMiddleware()

def register_function(self, fn, auth_required):
self.funcs[fn.__name__] = fn # needed by superclass methods
self.func_map[fn.__name__] = (auth_required, fn)
Expand Down Expand Up @@ -105,6 +108,8 @@ def _dispatch(self, request, method, params):
if not user:
raise Exception('Invalid username/password')

request.user = user
self.threadlocal.process_request(request)
params = (user,) + params

return fn(*params)
Expand Down

0 comments on commit 532baa9

Please sign in to comment.