blob: 40a1adb4cdb410128511df3160afa2f895df9a41 [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
Mitja Nikolaus1280ef42018-08-21 16:20:07 +02004from django.utils.decorators import method_decorator
5from rest_framework import status, generics
6from rest_framework.response import Response
7from rest_framework.exceptions import NotFound, ValidationError
8
Mitja Nikolaus4d759da2018-08-28 15:31:29 +02009from crashreports.permissions import (
10 HasRightsOrIsDeviceOwnerDeviceCreation,
11 SWAGGER_SECURITY_REQUIREMENTS_ALL,
12)
Dirk Vogtf2a33422016-10-11 17:17:26 +020013from crashreports.serializers import CrashReportSerializer
Mitja Nikolause2928eb2018-11-02 15:07:20 +010014from crashreports.utils import get_object_by_lookup_fields
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020015from crashreports.models import Crashreport
16from crashreports.response_descriptions import default_desc
Dirk Vogtf2a33422016-10-11 17:17:26 +020017
Dirk Vogtf2a33422016-10-11 17:17:26 +020018
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020019class CreateCrashreportResponseSchema(CrashReportSerializer):
20 """Response schema for successful crash report creation."""
21
22 class Meta: # noqa: D106
23 model = Crashreport
24 fields = ["device_local_id"]
25
26
27@method_decorator(
28 name="get",
Mitja Nikolaus4d759da2018-08-28 15:31:29 +020029 decorator=swagger_auto_schema(
30 operation_description="List crash reports",
31 security=SWAGGER_SECURITY_REQUIREMENTS_ALL,
32 ),
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020033)
34@method_decorator(
35 name="post",
36 decorator=swagger_auto_schema(
37 operation_description="Create a crash report",
Mitja Nikolaus4d759da2018-08-28 15:31:29 +020038 security=SWAGGER_SECURITY_REQUIREMENTS_ALL,
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020039 request_body=CrashReportSerializer,
40 responses=dict(
41 [
42 default_desc(ValidationError),
43 (
44 status.HTTP_404_NOT_FOUND,
45 openapi.Response(
46 "No device with the given uuid could be found."
47 ),
48 ),
49 (
50 status.HTTP_201_CREATED,
51 openapi.Response(
52 "The crash report has been successfully created.",
53 CreateCrashreportResponseSchema,
54 ),
55 ),
56 ]
57 ),
58 ),
59)
Dirk Vogte1784882016-10-13 16:09:38 +020060class ListCreateView(generics.ListCreateAPIView):
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020061 """Endpoint for listing crash reports and creating new crash reports."""
62
Dirk Vogtf2a33422016-10-11 17:17:26 +020063 queryset = Crashreport.objects.all()
64 paginate_by = 20
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020065 permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
Dirk Vogtf2a33422016-10-11 17:17:26 +020066 serializer_class = CrashReportSerializer
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020067 filter_fields = ("device", "build_fingerprint", "radio_version")
Dirk Vogt83107df2017-05-02 12:04:19 +020068
Mitja Nikolaus773d0cd2018-08-31 10:55:43 +020069 def dispatch(self, request, *args, **kwargs):
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020070 """Dispatch an incoming HTTP request to the right method.
71
72 The method is overridden in order to replace the 'device__uuid'
73 parameter value with the 'uuid' value from the parameters.
74 """
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020075 if "uuid" in kwargs:
Dirk Vogte1784882016-10-13 16:09:38 +020076 self.queryset = Crashreport.objects.filter(
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020077 device__uuid=kwargs["uuid"]
78 )
Mitja Nikolaus773d0cd2018-08-31 10:55:43 +020079 return generics.ListCreateAPIView.dispatch(
80 self, request, *args, **kwargs
81 )
Dirk Vogte1784882016-10-13 16:09:38 +020082
Dirk Vogteda80d32016-11-21 11:45:50 +010083 def perform_create(self, serializer):
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020084 """Create a crash report instance in the database.
85
86 The method is overridden in order to create a response containing only
87 the device_local_id.
88 """
Dirk Vogteda80d32016-11-21 11:45:50 +010089 serializer.save()
90 return Response(
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +020091 {"device_local_id": serializer.data["device_local_id"]},
92 status.HTTP_200_OK,
93 )
Dirk Vogteda80d32016-11-21 11:45:50 +010094
Dirk Vogte1784882016-10-13 16:09:38 +020095
Mitja Nikolaus1280ef42018-08-21 16:20:07 +020096@method_decorator(
97 name="get",
98 decorator=swagger_auto_schema(
99 operation_description="Get a crash report",
Mitja Nikolaus4d759da2018-08-28 15:31:29 +0200100 security=SWAGGER_SECURITY_REQUIREMENTS_ALL,
Mitja Nikolaus1280ef42018-08-21 16:20:07 +0200101 responses=dict([default_desc(NotFound)]),
102 ),
103)
104@method_decorator(
105 name="put",
106 decorator=swagger_auto_schema(
107 operation_description="Update a crash report",
Mitja Nikolaus4d759da2018-08-28 15:31:29 +0200108 security=SWAGGER_SECURITY_REQUIREMENTS_ALL,
Mitja Nikolaus1280ef42018-08-21 16:20:07 +0200109 responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
110 ),
111)
112@method_decorator(
113 name="patch",
114 decorator=swagger_auto_schema(
115 operation_description="Partially update a crash report",
Mitja Nikolaus4d759da2018-08-28 15:31:29 +0200116 security=SWAGGER_SECURITY_REQUIREMENTS_ALL,
Mitja Nikolaus1280ef42018-08-21 16:20:07 +0200117 responses=dict([default_desc(NotFound), default_desc(ValidationError)]),
118 ),
119)
120@method_decorator(
121 name="delete",
122 decorator=swagger_auto_schema(
123 operation_description="Delete a crash report",
Mitja Nikolaus4d759da2018-08-28 15:31:29 +0200124 security=SWAGGER_SECURITY_REQUIREMENTS_ALL,
Mitja Nikolaus1280ef42018-08-21 16:20:07 +0200125 responses=dict([default_desc(NotFound)]),
126 ),
127)
Dirk Vogte1784882016-10-13 16:09:38 +0200128class RetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView):
Mitja Nikolaus1280ef42018-08-21 16:20:07 +0200129 """Endpoint for retrieving, updating and deleting crash reports."""
130
131 # pylint: disable=too-many-ancestors
132
Dirk Vogte1784882016-10-13 16:09:38 +0200133 queryset = Crashreport.objects.all()
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200134 permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,)
Dirk Vogte1784882016-10-13 16:09:38 +0200135 serializer_class = CrashReportSerializer
Mitja Nikolauscb50f2c2018-08-24 13:54:48 +0200136 multiple_lookup_fields = {"id", "device__uuid", "device_local_id"}
Dirk Vogte1784882016-10-13 16:09:38 +0200137
138 def get_object(self):
Mitja Nikolaus1280ef42018-08-21 16:20:07 +0200139 """Retrieve a crash report."""
Mitja Nikolause2928eb2018-11-02 15:07:20 +0100140 return get_object_by_lookup_fields(self, self.multiple_lookup_fields)