blob: 78707b96d83590bd562728295f65ac0c1037b408 [file] [log] [blame]
Mitja Nikolaus1280ef42018-08-21 16:20:07 +02001"""REST API for accessing crash reports."""
2from drf_yasg import openapi
3from drf_yasg.utils import swagger_auto_schema
Dirk Vogte1784882016-10-13 16:09:38 +02004from django.shortcuts import get_object_or_404
Mitja Nikolaus1280ef42018-08-21 16:20:07 +02005from django.utils.decorators import method_decorator
6from rest_framework import status, generics
7from rest_framework.response import Response
8from rest_framework.exceptions import NotFound, ValidationError
9
Dirk Vogtc9e10ab2016-10-12 13:58:15 +020010from crashreports.permissions import HasRightsOrIsDeviceOwnerDeviceCreation
Dirk Vogtf2a33422016-10-11 17:17:26 +020011from crashreports.serializers import CrashReportSerializer
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020012from crashreports.models import Crashreport
13from crashreports.response_descriptions import default_desc
Dirk Vogtf2a33422016-10-11 17:17:26 +020014
Dirk Vogtf2a33422016-10-11 17:17:26 +020015
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020016class CreateCrashreportResponseSchema(CrashReportSerializer):
17 """Response schema for successful crash report creation."""
18
19 class Meta: # noqa: D106
20 model = Crashreport
21 fields = ["device_local_id"]
22
23
24@method_decorator(
25 name="get",
26 decorator=swagger_auto_schema(operation_description="List crash reports"),
27)
28@method_decorator(
29 name="post",
30 decorator=swagger_auto_schema(
31 operation_description="Create a crash report",
32 request_body=CrashReportSerializer,
33 responses=dict(
34 [
35 default_desc(ValidationError),
36 (
37 status.HTTP_404_NOT_FOUND,
38 openapi.Response(
39 "No device with the given uuid could be found."
40 ),
41 ),
42 (
43 status.HTTP_201_CREATED,
44 openapi.Response(
45 "The crash report has been successfully created.",
46 CreateCrashreportResponseSchema,
47 ),
48 ),
49 ]
50 ),
51 ),
52)
Dirk Vogte1784882016-10-13 16:09:38 +020053class ListCreateView(generics.ListCreateAPIView):
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020054 """Endpoint for listing crash reports and creating new crash reports."""
55
Dirk Vogtf2a33422016-10-11 17:17:26 +020056 queryset = Crashreport.objects.all()
57 paginate_by = 20
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020058 permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
Dirk Vogtf2a33422016-10-11 17:17:26 +020059 serializer_class = CrashReportSerializer
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020060 filter_fields = ("device", "build_fingerprint", "radio_version")
Dirk Vogt83107df2017-05-02 12:04:19 +020061
Mitja Nikolaus773d0cd2018-08-31 10:55:43 +020062 def dispatch(self, request, *args, **kwargs):
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020063 """Dispatch an incoming HTTP request to the right method.
64
65 The method is overridden in order to replace the 'device__uuid'
66 parameter value with the 'uuid' value from the parameters.
67 """
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020068 if "uuid" in kwargs:
Dirk Vogte1784882016-10-13 16:09:38 +020069 self.queryset = Crashreport.objects.filter(
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020070 device__uuid=kwargs["uuid"]
71 )
Mitja Nikolaus773d0cd2018-08-31 10:55:43 +020072 return generics.ListCreateAPIView.dispatch(
73 self, request, *args, **kwargs
74 )
Dirk Vogte1784882016-10-13 16:09:38 +020075
Dirk Vogteda80d32016-11-21 11:45:50 +010076 def perform_create(self, serializer):
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020077 """Create a crash report instance in the database.
78
79 The method is overridden in order to create a response containing only
80 the device_local_id.
81 """
Dirk Vogteda80d32016-11-21 11:45:50 +010082 serializer.save()
83 return Response(
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020084 {"device_local_id": serializer.data["device_local_id"]},
85 status.HTTP_200_OK,
86 )
Dirk Vogteda80d32016-11-21 11:45:50 +010087
Dirk Vogte1784882016-10-13 16:09:38 +020088
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020089@method_decorator(
90 name="get",
91 decorator=swagger_auto_schema(
92 operation_description="Get a crash report",
93 responses=dict([default_desc(NotFound)]),
94 ),
95)
96@method_decorator(
97 name="put",
98 decorator=swagger_auto_schema(
99 operation_description="Update a crash report",
100 responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
101 ),
102)
103@method_decorator(
104 name="patch",
105 decorator=swagger_auto_schema(
106 operation_description="Partially update a crash report",
107 responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
108 ),
109)
110@method_decorator(
111 name="delete",
112 decorator=swagger_auto_schema(
113 operation_description="Delete a crash report",
114 responses=dict([default_desc(NotFound)]),
115 ),
116)
Dirk Vogte1784882016-10-13 16:09:38 +0200117class RetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView):
Mitja Nikolaus1280ef42018-08-21 16:20:07 +0200118 """Endpoint for retrieving, updating and deleting crash reports."""
119
120 # pylint: disable=too-many-ancestors
121
Dirk Vogte1784882016-10-13 16:09:38 +0200122 queryset = Crashreport.objects.all()
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200123 permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
Dirk Vogte1784882016-10-13 16:09:38 +0200124 serializer_class = CrashReportSerializer
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200125 multiple_lookup_fields = {"id", "device__uuid", "device_local_id"}
Dirk Vogte1784882016-10-13 16:09:38 +0200126
127 def get_object(self):
Mitja Nikolaus1280ef42018-08-21 16:20:07 +0200128 """Retrieve a crash report."""
Dirk Vogte1784882016-10-13 16:09:38 +0200129 queryset = self.get_queryset()
Mitja Nikolaus1280ef42018-08-21 16:20:07 +0200130 query_filter = {}
Dirk Vogte1784882016-10-13 16:09:38 +0200131 for field in self.multiple_lookup_fields:
132 if field in self.kwargs:
Mitja Nikolaus1280ef42018-08-21 16:20:07 +0200133 query_filter[field] = self.kwargs[field]
134 obj = get_object_or_404(queryset, **query_filter)
Dirk Vogte1784882016-10-13 16:09:38 +0200135 self.check_object_permissions(self.request, obj)
136 return obj