blob: 17e0d772a3b8e5a7386c45dc8501ff0210df4d73 [file] [log] [blame]
"""REST API for accessing devices."""
from django.contrib.auth.models import Permission
from django.utils.decorators import method_decorator
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import generics, status
from rest_framework.exceptions import NotFound, ValidationError
from rest_framework.authtoken.models import Token
from rest_framework.decorators import api_view, permission_classes
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from crashreports.models import Device, User
from crashreports.permissions import HasRightsOrIsDeviceOwnerDeviceCreation
from crashreports.serializers import DeviceSerializer, DeviceCreateSerializer
from crashreports.response_descriptions import default_desc
@method_decorator(name='get', decorator=swagger_auto_schema(
operation_description='List devices'))
@method_decorator(name='post', decorator=swagger_auto_schema(
operation_description='Create a device',
responses=dict([default_desc(ValidationError)])))
class ListCreateDevices(generics.ListCreateAPIView):
"""Endpoint for listing devices and creating new devices."""
queryset = Device.objects.all()
paginate_by = 20
permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation, )
serializer_class = DeviceSerializer
filter_fields = ('uuid', 'board_date', 'chipset')
@method_decorator(name='get', decorator=swagger_auto_schema(
operation_description='Get a device',
responses=dict([default_desc(NotFound)])))
@method_decorator(name='put', decorator=swagger_auto_schema(
operation_description='Update a device',
responses=dict([default_desc(NotFound), default_desc(ValidationError)])))
@method_decorator(name='patch', decorator=swagger_auto_schema(
operation_description='Make a partial update for a device',
responses=dict([default_desc(NotFound), default_desc(ValidationError)])))
@method_decorator(name='delete', decorator=swagger_auto_schema(
operation_description='Delete a device',
responses=dict([default_desc(NotFound)])))
class RetrieveUpdateDestroyDevice(generics.RetrieveUpdateDestroyAPIView):
"""Endpoint for retrieving, updating, patching and deleting devices."""
# pylint: disable=too-many-ancestors
queryset = Device.objects.all()
permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation, )
serializer_class = DeviceSerializer
lookup_field = 'uuid'
class DeviceRegisterResponseSchema(DeviceSerializer):
"""Response schema for successful device registration."""
class Meta: # noqa: D106
model = Device
fields = ['uuid', 'token']
@swagger_auto_schema(
method='post',
request_body=DeviceCreateSerializer,
responses=dict([
default_desc(ValidationError),
(status.HTTP_200_OK,
openapi.Response('The device has been successfully registered.',
DeviceRegisterResponseSchema))
]))
@api_view(http_method_names=['POST'], )
@permission_classes((AllowAny,))
def register_device(request):
"""Register a new device.
This endpoint will generate a django user for the new device. The device is
identified by a uuid, and authenticated with a token.
We generate the uuid here as this makes it easier to deal with collisions.
"""
serializer = DeviceCreateSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
device = Device()
user = User.objects.create_user("device_" + str(device.uuid), '', None)
permission = Permission.objects.get(name='Can add crashreport')
user.user_permissions.add(permission)
user.save()
device.board_date = serializer.validated_data['board_date']
device.chipset = serializer.validated_data['chipset']
device.user = user
device.token = Token.objects.create(user=user).key
device.save()
return Response({'uuid': device.uuid, 'token': device.token})