Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 1 | """REST API for accessing crash reports.""" |
| 2 | from drf_yasg import openapi |
| 3 | from drf_yasg.utils import swagger_auto_schema |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 4 | from django.utils.decorators import method_decorator |
| 5 | from rest_framework import status, generics |
| 6 | from rest_framework.response import Response |
| 7 | from rest_framework.exceptions import NotFound, ValidationError |
| 8 | |
Mitja Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 9 | from crashreports.permissions import ( |
| 10 | HasRightsOrIsDeviceOwnerDeviceCreation, |
| 11 | SWAGGER_SECURITY_REQUIREMENTS_ALL, |
| 12 | ) |
Dirk Vogt | f2a3342 | 2016-10-11 17:17:26 +0200 | [diff] [blame] | 13 | from crashreports.serializers import CrashReportSerializer |
Mitja Nikolaus | e2928eb | 2018-11-02 15:07:20 +0100 | [diff] [blame] | 14 | from crashreports.utils import get_object_by_lookup_fields |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 15 | from crashreports.models import Crashreport |
| 16 | from crashreports.response_descriptions import default_desc |
Dirk Vogt | f2a3342 | 2016-10-11 17:17:26 +0200 | [diff] [blame] | 17 | |
Dirk Vogt | f2a3342 | 2016-10-11 17:17:26 +0200 | [diff] [blame] | 18 | |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 19 | class 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 Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 29 | decorator=swagger_auto_schema( |
| 30 | operation_description="List crash reports", |
| 31 | security=SWAGGER_SECURITY_REQUIREMENTS_ALL, |
| 32 | ), |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 33 | ) |
| 34 | @method_decorator( |
| 35 | name="post", |
| 36 | decorator=swagger_auto_schema( |
| 37 | operation_description="Create a crash report", |
Mitja Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 38 | security=SWAGGER_SECURITY_REQUIREMENTS_ALL, |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 39 | 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 Vogt | e178488 | 2016-10-13 16:09:38 +0200 | [diff] [blame] | 60 | class ListCreateView(generics.ListCreateAPIView): |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 61 | """Endpoint for listing crash reports and creating new crash reports.""" |
| 62 | |
Dirk Vogt | f2a3342 | 2016-10-11 17:17:26 +0200 | [diff] [blame] | 63 | queryset = Crashreport.objects.all() |
| 64 | paginate_by = 20 |
Mitja Nikolaus | cb50f2c | 2018-08-24 13:54:48 +0200 | [diff] [blame] | 65 | permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,) |
Dirk Vogt | f2a3342 | 2016-10-11 17:17:26 +0200 | [diff] [blame] | 66 | serializer_class = CrashReportSerializer |
Mitja Nikolaus | cb50f2c | 2018-08-24 13:54:48 +0200 | [diff] [blame] | 67 | filter_fields = ("device", "build_fingerprint", "radio_version") |
Dirk Vogt | 83107df | 2017-05-02 12:04:19 +0200 | [diff] [blame] | 68 | |
Mitja Nikolaus | 773d0cd | 2018-08-31 10:55:43 +0200 | [diff] [blame] | 69 | def dispatch(self, request, *args, **kwargs): |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 70 | """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 Nikolaus | cb50f2c | 2018-08-24 13:54:48 +0200 | [diff] [blame] | 75 | if "uuid" in kwargs: |
Dirk Vogt | e178488 | 2016-10-13 16:09:38 +0200 | [diff] [blame] | 76 | self.queryset = Crashreport.objects.filter( |
Mitja Nikolaus | cb50f2c | 2018-08-24 13:54:48 +0200 | [diff] [blame] | 77 | device__uuid=kwargs["uuid"] |
| 78 | ) |
Mitja Nikolaus | 773d0cd | 2018-08-31 10:55:43 +0200 | [diff] [blame] | 79 | return generics.ListCreateAPIView.dispatch( |
| 80 | self, request, *args, **kwargs |
| 81 | ) |
Dirk Vogt | e178488 | 2016-10-13 16:09:38 +0200 | [diff] [blame] | 82 | |
Dirk Vogt | eda80d3 | 2016-11-21 11:45:50 +0100 | [diff] [blame] | 83 | def perform_create(self, serializer): |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 84 | """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 Vogt | eda80d3 | 2016-11-21 11:45:50 +0100 | [diff] [blame] | 89 | serializer.save() |
| 90 | return Response( |
Mitja Nikolaus | cb50f2c | 2018-08-24 13:54:48 +0200 | [diff] [blame] | 91 | {"device_local_id": serializer.data["device_local_id"]}, |
| 92 | status.HTTP_200_OK, |
| 93 | ) |
Dirk Vogt | eda80d3 | 2016-11-21 11:45:50 +0100 | [diff] [blame] | 94 | |
Dirk Vogt | e178488 | 2016-10-13 16:09:38 +0200 | [diff] [blame] | 95 | |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 96 | @method_decorator( |
| 97 | name="get", |
| 98 | decorator=swagger_auto_schema( |
| 99 | operation_description="Get a crash report", |
Mitja Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 100 | security=SWAGGER_SECURITY_REQUIREMENTS_ALL, |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 101 | 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 Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 108 | security=SWAGGER_SECURITY_REQUIREMENTS_ALL, |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 109 | 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 Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 116 | security=SWAGGER_SECURITY_REQUIREMENTS_ALL, |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 117 | 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 Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 124 | security=SWAGGER_SECURITY_REQUIREMENTS_ALL, |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 125 | responses=dict([default_desc(NotFound)]), |
| 126 | ), |
| 127 | ) |
Dirk Vogt | e178488 | 2016-10-13 16:09:38 +0200 | [diff] [blame] | 128 | class RetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView): |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 129 | """Endpoint for retrieving, updating and deleting crash reports.""" |
| 130 | |
| 131 | # pylint: disable=too-many-ancestors |
| 132 | |
Dirk Vogt | e178488 | 2016-10-13 16:09:38 +0200 | [diff] [blame] | 133 | queryset = Crashreport.objects.all() |
Mitja Nikolaus | cb50f2c | 2018-08-24 13:54:48 +0200 | [diff] [blame] | 134 | permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,) |
Dirk Vogt | e178488 | 2016-10-13 16:09:38 +0200 | [diff] [blame] | 135 | serializer_class = CrashReportSerializer |
Mitja Nikolaus | cb50f2c | 2018-08-24 13:54:48 +0200 | [diff] [blame] | 136 | multiple_lookup_fields = {"id", "device__uuid", "device_local_id"} |
Dirk Vogt | e178488 | 2016-10-13 16:09:38 +0200 | [diff] [blame] | 137 | |
| 138 | def get_object(self): |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 139 | """Retrieve a crash report.""" |
Mitja Nikolaus | e2928eb | 2018-11-02 15:07:20 +0100 | [diff] [blame] | 140 | return get_object_by_lookup_fields(self, self.multiple_lookup_fields) |