blob: 17e0d772a3b8e5a7386c45dc8501ff0210df4d73 [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
20@method_decorator(name='get', decorator=swagger_auto_schema(
21 operation_description='List devices'))
22@method_decorator(name='post', decorator=swagger_auto_schema(
23 operation_description='Create a device',
24 responses=dict([default_desc(ValidationError)])))
Dirk Vogtf2a33422016-10-11 17:17:26 +020025class ListCreateDevices(generics.ListCreateAPIView):
Mitja Nikolause9208082018-07-30 14:22:09 +020026 """Endpoint for listing devices and creating new devices."""
27
Dirk Vogtf2a33422016-10-11 17:17:26 +020028 queryset = Device.objects.all()
29 paginate_by = 20
Dirk Vogtf3662f62016-12-12 16:43:06 +010030 permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation, )
Dirk Vogtf2a33422016-10-11 17:17:26 +020031 serializer_class = DeviceSerializer
Dirk Vogt83107df2017-05-02 12:04:19 +020032 filter_fields = ('uuid', 'board_date', 'chipset')
Dirk Vogtf2a33422016-10-11 17:17:26 +020033
Dirk Vogt7160b5e2016-10-12 17:04:40 +020034
Mitja Nikolause9208082018-07-30 14:22:09 +020035@method_decorator(name='get', decorator=swagger_auto_schema(
36 operation_description='Get a device',
37 responses=dict([default_desc(NotFound)])))
38@method_decorator(name='put', decorator=swagger_auto_schema(
39 operation_description='Update a device',
40 responses=dict([default_desc(NotFound), default_desc(ValidationError)])))
41@method_decorator(name='patch', decorator=swagger_auto_schema(
42 operation_description='Make a partial update for a device',
43 responses=dict([default_desc(NotFound), default_desc(ValidationError)])))
44@method_decorator(name='delete', decorator=swagger_auto_schema(
45 operation_description='Delete a device',
46 responses=dict([default_desc(NotFound)])))
Dirk Vogtf2a33422016-10-11 17:17:26 +020047class RetrieveUpdateDestroyDevice(generics.RetrieveUpdateDestroyAPIView):
Mitja Nikolause9208082018-07-30 14:22:09 +020048 """Endpoint for retrieving, updating, patching and deleting devices."""
49
50 # pylint: disable=too-many-ancestors
51
Dirk Vogtf2a33422016-10-11 17:17:26 +020052 queryset = Device.objects.all()
Dirk Vogtf3662f62016-12-12 16:43:06 +010053 permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation, )
Dirk Vogtf2a33422016-10-11 17:17:26 +020054 serializer_class = DeviceSerializer
55 lookup_field = 'uuid'
Dirk Vogtf2a33422016-10-11 17:17:26 +020056
Dirk Vogt7160b5e2016-10-12 17:04:40 +020057
Mitja Nikolause9208082018-07-30 14:22:09 +020058class DeviceRegisterResponseSchema(DeviceSerializer):
59 """Response schema for successful device registration."""
60
61 class Meta: # noqa: D106
62 model = Device
63 fields = ['uuid', 'token']
64
65
66@swagger_auto_schema(
67 method='post',
68 request_body=DeviceCreateSerializer,
69 responses=dict([
70 default_desc(ValidationError),
71 (status.HTTP_200_OK,
72 openapi.Response('The device has been successfully registered.',
73 DeviceRegisterResponseSchema))
74 ]))
Dirk Vogtf2a33422016-10-11 17:17:26 +020075@api_view(http_method_names=['POST'], )
76@permission_classes((AllowAny,))
77def register_device(request):
Mitja Nikolause9208082018-07-30 14:22:09 +020078 """Register a new device.
79
80 This endpoint will generate a django user for the new device. The device is
81 identified by a uuid, and authenticated with a token.
Dirk Vogt7160b5e2016-10-12 17:04:40 +020082 We generate the uuid here as this makes it easier to deal with collisions.
Dirk Vogtf2a33422016-10-11 17:17:26 +020083 """
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +010084 serializer = DeviceCreateSerializer(data=request.data)
85 serializer.is_valid(raise_exception=True)
Dirk Vogtf2a33422016-10-11 17:17:26 +020086 device = Device()
Dirk Vogt7160b5e2016-10-12 17:04:40 +020087 user = User.objects.create_user("device_" + str(device.uuid), '', None)
Dirk Vogtf2a33422016-10-11 17:17:26 +020088 permission = Permission.objects.get(name='Can add crashreport')
89 user.user_permissions.add(permission)
90 user.save()
Franz-Xaver Geigerd9943352018-02-27 14:26:41 +010091 device.board_date = serializer.validated_data['board_date']
92 device.chipset = serializer.validated_data['chipset']
Dirk Vogtf2a33422016-10-11 17:17:26 +020093 device.user = user
Dirk Vogt7160b5e2016-10-12 17:04:40 +020094 device.token = Token.objects.create(user=user).key
Dirk Vogtf2a33422016-10-11 17:17:26 +020095 device.save()
Dirk Vogt7160b5e2016-10-12 17:04:40 +020096 return Response({'uuid': device.uuid, 'token': device.token})