0

I made an endpoint called /cars. A person can create cars with a frontend, but devices read cars using an SDK, which has an API Key. This way, 2 rent-a-car companies can use the API without getting the cars mixed-up. Each app has its own API Key and its own person managing the contents.

This is being implemented with django restframework 3.x and django-oauth-toolkit.

I'm writing a test for a human retrieving cars, and another for a device.

This is failing:

def test_get_list(self): # devices have a django user (AUTH_USER_MODEL ---onetoone--- Device) self.client.force_authenticate(user=self.user_device) self._get_list() self.client.force_authenticate(user=None) 

force_authentication sets request.auth to None. However, with postman or httpie, request.auth contains the Application object.

The queryset is:

def get_queryset(self): if hasattr(self.request.user, 'device'): # get the cars created by the owner of the API Key return self.request.auth.application.user.cars.all() return self.request.user.cars.all() # get my cars 
  1. Does this approach in the queryset make sense?
  2. Am I testing it in the wrong way?
  3. Why is request.auth empty? Is force_authentication using BasicAuthentication?

2 Answers 2

2
  1. I would recommend going with check_object_permission for this kind of checks. You can read more here.

  2. DRF documentation states that you need to force_authenticate the request if you are using APIRequestFactory. From the documentation:

    from rest_framework.test import force_authenticate factory = APIRequestFactory() user = User.objects.get(username='olivia') view = AccountDetail.as_view() # Make an authenticated request to the view... request = factory.get('/accounts/django-superstars/') force_authenticate(request, user=user) response = view(request) 

    To authenticate with APIClient try using credentials. Example from the documentation:

    from rest_framework.authtoken.models import Token from rest_framework.test import APIClient # Include an appropriate `Authorization:` header on all requests. token = Token.objects.get(user__username='lauren') client = APIClient() client.credentials(HTTP_AUTHORIZATION='Token ' + token.key) 
  3. The same is the second question.

Sign up to request clarification or add additional context in comments.

1 Comment

things make so much sense all of a sudden. thanks! I got it working.
1

As pointed in the documentation force_authenticate bypass authentication therefore it's your job to simulate the missing authentication part, including filling the request.auth.

Otherwise, you'll need to configure a data set and call either login or credential on the APIClient instance.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.