| """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}) |