Search code examples
djangotastypie

Exposing Django model method using TastyPie with Authentication


I'm trying to expose my Django model method using TastyPie and secure resulting endpoint by using BasicAuthentication, also I need to pass Django user authenticated with BasicAuthentication into my method:

class TaskResource(ModelResource):
class Meta:
    queryset = Task.objects.all()
    resource_name = 'jenkins_task'
    excludes = ['id', 'jenkins_job_name']
    authentication = BasicAuthentication()


def prepend_urls(self):
    """ Add the following array of urls to the TaskResource base urls """
    return [
        url(r"^(?P<resource_name>%s)/(?P<pk>\w[\w/-]*)/run%s$" %
            (self._meta.resource_name, trailing_slash()),
            self.wrap_view('run'), name="api_task_run"),
    ]


def run(self, request, **kwargs):
     """ proxy for the Task.call_api method """ 

     # create a basic bundle object for self.get_cached_obj_get.
     basic_bundle = self.build_bundle(request=request)

     print('User: %s' % basic_bundle.request.user)

     # using the primary key defined in the url, obtain the task
     task = self.cached_obj_get(
         bundle=basic_bundle,
         **self.remove_api_resource_names(kwargs))

     # Return what the method output, tastypie will handle the serialization
     return self.create_response(request, task.call_api(basic_bundle.request))

I'm sending following POST request:

Preparing request to http://127.0.0.1:8991/api/jenkins_task/7/run/
Using libcurl/7.54.0 LibreSSL/2.0.20 zlib/1.2.11 nghttp2/1.24.0
Connected to 127.0.0.1 (127.0.0.1) port 8991 (#48)
Server auth using Basic with user 'integration'

POST /api/jenkins_task/7/run/ HTTP/1.1
Host: 127.0.0.1:8991
Authorization: Basic aW50ZWdyYXRpb246aW50ZWdyYXRpb24=
User-Agent: insomnia/5.15.0
Content-Type: application/json
Accept: */*
Content-Length: 67
{
    "snow_number": "INC000000",
    "Store": "0940",
    "Service": "RE"
 }

However, I got code 500, basically because the internal logic inside task.call_api method is not able to find basic_bundle.request.user.

So, my question is how come variable request passed to run() method does not contain Django user if it just has been authenticated? Is there something I miss?

Also, print('User: %s' % basic_bundle.request.user) return User: AnonymousUser into Django log


Solution

  • The view needs to authenticate the user. Custom endpoints have to do this, as seen in the example of a search endpoint. Check out Resource.dispatch for other bits and pieces that you might need to do in custom views.

    The Django user is added to the request after successful authentication.