Reputation: 8031
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
Upvotes: 0
Views: 888
Reputation: 20996
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.
Upvotes: 1
Reputation: 558
I would recommend going with check_object_permission
for this kind of checks. You can read more here.
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)
The same is the second question.
Upvotes: 2