Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 1 | """REST API for accessing log files.""" |
| 2 | from django.core.exceptions import ObjectDoesNotExist |
| 3 | from django.utils.decorators import method_decorator |
| 4 | from drf_yasg import openapi |
| 5 | from drf_yasg.utils import swagger_auto_schema |
Dirk Vogt | 7160b5e | 2016-10-12 17:04:40 +0200 | [diff] [blame] | 6 | |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 7 | from rest_framework import generics, status |
| 8 | from rest_framework.decorators import ( |
| 9 | api_view, |
| 10 | parser_classes, |
| 11 | permission_classes, |
| 12 | ) |
| 13 | from rest_framework.exceptions import ( |
| 14 | PermissionDenied, |
| 15 | NotFound, |
| 16 | ValidationError, |
| 17 | ) |
Dirk Vogt | 7160b5e | 2016-10-12 17:04:40 +0200 | [diff] [blame] | 18 | from rest_framework.parsers import FileUploadParser |
| 19 | from rest_framework.permissions import IsAuthenticated |
Dirk Vogt | 7160b5e | 2016-10-12 17:04:40 +0200 | [diff] [blame] | 20 | from rest_framework.response import Response |
Dirk Vogt | 83107df | 2017-05-02 12:04:19 +0200 | [diff] [blame] | 21 | |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 22 | from crashreports.response_descriptions import default_desc |
Dirk Vogt | 83107df | 2017-05-02 12:04:19 +0200 | [diff] [blame] | 23 | from crashreports.serializers import LogFileSerializer |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 24 | from crashreports.models import Crashreport, LogFile |
| 25 | from crashreports.permissions import ( |
| 26 | HasRightsOrIsDeviceOwnerDeviceCreation, |
| 27 | user_owns_uuid, |
| 28 | user_is_hiccup_staff, |
Mitja Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 29 | SWAGGER_SECURITY_REQUIREMENTS_ALL, |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 30 | ) |
Dirk Vogt | 83107df | 2017-05-02 12:04:19 +0200 | [diff] [blame] | 31 | |
| 32 | |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 33 | @method_decorator( |
| 34 | name="get", |
Mitja Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 35 | decorator=swagger_auto_schema( |
| 36 | operation_description="List log files", |
| 37 | security=SWAGGER_SECURITY_REQUIREMENTS_ALL, |
| 38 | ), |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 39 | ) |
Mitja Nikolaus | 0343baf | 2018-09-03 11:56:31 +0200 | [diff] [blame] | 40 | class ListView(generics.ListAPIView): |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 41 | """Endpoint for listing log files.""" |
| 42 | |
Dirk Vogt | 83107df | 2017-05-02 12:04:19 +0200 | [diff] [blame] | 43 | queryset = LogFile.objects.all() |
Mitja Nikolaus | cb50f2c | 2018-08-24 13:54:48 +0200 | [diff] [blame] | 44 | permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,) |
Dirk Vogt | 83107df | 2017-05-02 12:04:19 +0200 | [diff] [blame] | 45 | serializer_class = LogFileSerializer |
| 46 | |
| 47 | |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 48 | @method_decorator( |
| 49 | name="get", |
| 50 | decorator=swagger_auto_schema( |
| 51 | operation_description="Get a log file", |
Mitja Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 52 | security=SWAGGER_SECURITY_REQUIREMENTS_ALL, |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 53 | responses=dict([default_desc(NotFound)]), |
| 54 | ), |
| 55 | ) |
| 56 | @method_decorator( |
| 57 | name="put", |
| 58 | decorator=swagger_auto_schema( |
| 59 | operation_description="Update a log file", |
Mitja Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 60 | security=SWAGGER_SECURITY_REQUIREMENTS_ALL, |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 61 | responses=dict([default_desc(NotFound), default_desc(ValidationError)]), |
| 62 | ), |
| 63 | ) |
| 64 | @method_decorator( |
| 65 | name="patch", |
| 66 | decorator=swagger_auto_schema( |
| 67 | operation_description="Partially update a log file", |
Mitja Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 68 | security=SWAGGER_SECURITY_REQUIREMENTS_ALL, |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 69 | responses=dict([default_desc(NotFound), default_desc(ValidationError)]), |
| 70 | ), |
| 71 | ) |
| 72 | @method_decorator( |
| 73 | name="delete", |
| 74 | decorator=swagger_auto_schema( |
| 75 | operation_description="Delete a log file", |
Mitja Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 76 | security=SWAGGER_SECURITY_REQUIREMENTS_ALL, |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 77 | responses=dict([default_desc(NotFound)]), |
| 78 | ), |
| 79 | ) |
Dirk Vogt | 83107df | 2017-05-02 12:04:19 +0200 | [diff] [blame] | 80 | class RetrieveUpdateDestroyView(generics.RetrieveUpdateDestroyAPIView): |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 81 | """Endpoint for retrieving, updating and deleting log files.""" |
| 82 | |
| 83 | # pylint: disable=too-many-ancestors |
| 84 | |
Dirk Vogt | 83107df | 2017-05-02 12:04:19 +0200 | [diff] [blame] | 85 | queryset = LogFile.objects.all() |
Mitja Nikolaus | cb50f2c | 2018-08-24 13:54:48 +0200 | [diff] [blame] | 86 | permission_classes = (HasRightsOrIsDeviceOwnerDeviceCreation,) |
Dirk Vogt | 83107df | 2017-05-02 12:04:19 +0200 | [diff] [blame] | 87 | serializer_class = LogFileSerializer |
Dirk Vogt | 7160b5e | 2016-10-12 17:04:40 +0200 | [diff] [blame] | 88 | |
| 89 | |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 90 | @swagger_auto_schema( |
| 91 | method="post", |
Mitja Nikolaus | 4d759da | 2018-08-28 15:31:29 +0200 | [diff] [blame] | 92 | security=SWAGGER_SECURITY_REQUIREMENTS_ALL, |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 93 | request_body=LogFileSerializer, |
| 94 | responses=dict( |
| 95 | [ |
| 96 | default_desc(ValidationError), |
| 97 | ( |
| 98 | status.HTTP_404_NOT_FOUND, |
| 99 | openapi.Response("Crashreport does not exist."), |
| 100 | ), |
| 101 | (status.HTTP_201_CREATED, openapi.Response("Created")), |
| 102 | ] |
| 103 | ), |
| 104 | ) |
Mitja Nikolaus | cb50f2c | 2018-08-24 13:54:48 +0200 | [diff] [blame] | 105 | @api_view(http_method_names=["POST"]) |
| 106 | @parser_classes([FileUploadParser]) |
| 107 | @permission_classes([IsAuthenticated]) |
Dirk Vogt | 3663569 | 2016-10-17 12:19:10 +0200 | [diff] [blame] | 108 | def logfile_put(request, uuid, device_local_id, filename): |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 109 | """Upload a log file for a crash report.""" |
Dirk Vogt | 7160b5e | 2016-10-12 17:04:40 +0200 | [diff] [blame] | 110 | try: |
Mitja Nikolaus | cb50f2c | 2018-08-24 13:54:48 +0200 | [diff] [blame] | 111 | crashreport = Crashreport.objects.get( |
| 112 | device__uuid=uuid, device_local_id=device_local_id |
| 113 | ) |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 114 | except ObjectDoesNotExist: |
Dirk Vogt | 3663569 | 2016-10-17 12:19:10 +0200 | [diff] [blame] | 115 | raise NotFound(detail="Crashreport does not exist.") |
| 116 | |
Mitja Nikolaus | cb50f2c | 2018-08-24 13:54:48 +0200 | [diff] [blame] | 117 | if not ( |
| 118 | user_owns_uuid(request.user, crashreport.device.uuid) |
| 119 | or user_is_hiccup_staff(request.user) |
| 120 | ): |
Dirk Vogt | 7160b5e | 2016-10-12 17:04:40 +0200 | [diff] [blame] | 121 | raise PermissionDenied(detail="Not allowed.") |
Mitja Nikolaus | 1280ef4 | 2018-08-21 16:20:07 +0200 | [diff] [blame] | 122 | file = request.data["file"] |
| 123 | logfile = LogFile(crashreport=crashreport, logfile=file) |
Dirk Vogt | 7160b5e | 2016-10-12 17:04:40 +0200 | [diff] [blame] | 124 | logfile.save() |
Dirk Vogt | 3663569 | 2016-10-17 12:19:10 +0200 | [diff] [blame] | 125 | return Response(status=201) |