blob: 96923b2bb817bcbeef62aad8e8633f5a0ab8eb55 [file] [log] [blame]
Mitja Nikolause9208082018-07-30 14:22:09 +02001"""REST API for accessing devices."""
2
3from django.contrib.auth.models import Permission
4from django.utils.decorators import method_decorator
5from drf_yasg import openapi
6from drf_yasg.utils import swagger_auto_schema
7from rest_framework import generics, status
8from rest_framework.exceptions import NotFound, ValidationError
9from rest_framework.authtoken.models import Token
10from rest_framework.decorators import api_view, permission_classes
11from rest_framework.permissions import AllowAny
12from rest_framework.response import Response
13
14from crashreports.models import Device, User
Dirk Vogtf3662f62016-12-12 16:43:06 +010015from crashreports.permissions import HasRightsOrIsDeviceOwnerDeviceCreation
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +010016from crashreports.serializers import DeviceSerializer, DeviceCreateSerializer
Mitja Nikolause9208082018-07-30 14:22:09 +020017from crashreports.response_descriptions import default_desc
Dirk Vogt7160b5e2016-10-12 17:04:40 +020018
Mitja Nikolause9208082018-07-30 14:22:09 +020019
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020020@method_decorator(
21 name="get",
22 decorator=swagger_auto_schema(operation_description="List devices"),
23)
24@method_decorator(
25 name="post",
26 decorator=swagger_auto_schema(
27 operation_description="Create a device",
28 responses=dict([default_desc(ValidationError)]),
29 ),
30)
Dirk Vogtf2a33422016-10-11 17:17:26 +020031class ListCreateDevices(generics.ListCreateAPIView):
Mitja Nikolause9208082018-07-30 14:22:09 +020032 """Endpoint for listing devices and creating new devices."""
33
Dirk Vogtf2a33422016-10-11 17:17:26 +020034 queryset = Device.objects.all()
35 paginate_by = 20
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020036 permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
Dirk Vogtf2a33422016-10-11 17:17:26 +020037 serializer_class = DeviceSerializer
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020038 filter_fields = ("uuid", "board_date", "chipset")
Dirk Vogtf2a33422016-10-11 17:17:26 +020039
Dirk Vogt7160b5e2016-10-12 17:04:40 +020040
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020041@method_decorator(
42 name="get",
43 decorator=swagger_auto_schema(
44 operation_description="Get a device",
45 responses=dict([default_desc(NotFound)]),
46 ),
47)
48@method_decorator(
49 name="put",
50 decorator=swagger_auto_schema(
51 operation_description="Update a device",
52 responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
53 ),
54)
55@method_decorator(
56 name="patch",
57 decorator=swagger_auto_schema(
58 operation_description="Make a partial update for a device",
59 responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
60 ),
61)
62@method_decorator(
63 name="delete",
64 decorator=swagger_auto_schema(
65 operation_description="Delete a device",
66 responses=dict([default_desc(NotFound)]),
67 ),
68)
Dirk Vogtf2a33422016-10-11 17:17:26 +020069class RetrieveUpdateDestroyDevice(generics.RetrieveUpdateDestroyAPIView):
Mitja Nikolause9208082018-07-30 14:22:09 +020070 """Endpoint for retrieving, updating, patching and deleting devices."""
71
72 # pylint: disable=too-many-ancestors
73
Dirk Vogtf2a33422016-10-11 17:17:26 +020074 queryset = Device.objects.all()
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020075 permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
Dirk Vogtf2a33422016-10-11 17:17:26 +020076 serializer_class = DeviceSerializer
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020077 lookup_field = "uuid"
Dirk Vogtf2a33422016-10-11 17:17:26 +020078
Dirk Vogt7160b5e2016-10-12 17:04:40 +020079
Mitja Nikolause9208082018-07-30 14:22:09 +020080class DeviceRegisterResponseSchema(DeviceSerializer):
81 """Response schema for successful device registration."""
82
83 class Meta: # noqa: D106
84 model = Device
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020085 fields = ["uuid", "token"]
Mitja Nikolause9208082018-07-30 14:22:09 +020086
87
88@swagger_auto_schema(
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020089 method="post",
Mitja Nikolause9208082018-07-30 14:22:09 +020090 request_body=DeviceCreateSerializer,
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020091 responses=dict(
92 [
93 default_desc(ValidationError),
94 (
95 status.HTTP_200_OK,
96 openapi.Response(
97 "The device has been successfully registered.",
98 DeviceRegisterResponseSchema,
99 ),
100 ),
101 ]
102 ),
103)
104@api_view(http_method_names=["POST"])
Dirk Vogtf2a33422016-10-11 17:17:26 +0200105@permission_classes((AllowAny,))
106def register_device(request):
Mitja Nikolause9208082018-07-30 14:22:09 +0200107 """Register a new device.
108
109 This endpoint will generate a django user for the new device. The device is
110 identified by a uuid, and authenticated with a token.
Dirk Vogt7160b5e2016-10-12 17:04:40 +0200111 We generate the uuid here as this makes it easier to deal with collisions.
Dirk Vogtf2a33422016-10-11 17:17:26 +0200112 """
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +0100113 serializer = DeviceCreateSerializer(data=request.data)
114 serializer.is_valid(raise_exception=True)
Dirk Vogtf2a33422016-10-11 17:17:26 +0200115 device = Device()
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200116 user = User.objects.create_user("device_" + str(device.uuid), "", None)
117 permission = Permission.objects.get(name="Can add crashreport")
Dirk Vogtf2a33422016-10-11 17:17:26 +0200118 user.user_permissions.add(permission)
119 user.save()
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200120 device.board_date = serializer.validated_data["board_date"]
121 device.chipset = serializer.validated_data["chipset"]
Dirk Vogtf2a33422016-10-11 17:17:26 +0200122 device.user = user
Dirk Vogt7160b5e2016-10-12 17:04:40 +0200123 device.token = Token.objects.create(user=user).key
Dirk Vogtf2a33422016-10-11 17:17:26 +0200124 device.save()
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200125 return Response({"uuid": device.uuid, "token": device.token})