blob: 3efb1de782aa9e8ea9f9f729579ea8a16ec8e8d3 [file] [log] [blame]
Scott Baker8974e552015-02-10 19:26:00 -08001from rest_framework.response import Response
2from rest_framework import serializers
3from rest_framework import generics
4from rest_framework import status
5from rest_framework.exceptions import PermissionDenied as RestFrameworkPermissionDenied
6from django.core.exceptions import PermissionDenied as DjangoPermissionDenied
7
8class XOSRetrieveUpdateDestroyAPIView(generics.RetrieveUpdateDestroyAPIView):
9
10 # To handle fine-grained field permissions, we have to check can_update
11 # the object has been updated but before it has been saved.
12
13 def update(self, request, *args, **kwargs):
14 partial = kwargs.pop('partial', False)
15 self.object = self.get_object_or_none()
16
17 if self.object is None:
18 raise Exception("Use the List API for creating objects")
19
20 serializer = self.get_serializer(self.object, data=request.DATA,
21 files=request.FILES, partial=partial)
22
23 assert(serializer.object is not None)
24
25 serializer.object.caller = request.user
26
27 if not serializer.is_valid():
28 response = {"error": "validation",
29 "specific_error": "not serializer.is_valid()",
30 "reasons": serializer.errors}
31 return Response(response, status=status.HTTP_400_BAD_REQUEST)
32
33 try:
34 self.pre_save(serializer.object)
35 except ValidationError as err:
36 # full_clean on model instance may be called in pre_save,
37 # so we have to handle eventual errors.
38 response = {"error": "validation",
39 "specific_error": "ValidationError in pre_save",
40 "reasons": err.message_dict}
41 return Response(response, status=status.HTTP_400_BAD_REQUEST)
42
43 if not serializer.object.can_update(request.user):
44 return Response(status=status.HTTP_400_BAD_REQUEST)
45
46 self.object = serializer.save(force_update=True)
47 self.post_save(self.object, created=False)
48 return Response(serializer.data, status=status.HTTP_200_OK)
49
50 def destroy(self, request, *args, **kwargs):
51 obj = self.get_object()
52 if obj.can_update(request.user):
53 return super(XOSRetrieveUpdateDestroyAPIView, self).destroy(request, *args, **kwargs)
54 else:
55 return Response(status=status.HTTP_400_BAD_REQUEST)
56
57 def handle_exception(self, exc):
58 # REST API drops the string attached to Django's PermissionDenied
59 # exception, and replaces it with a generic "Permission Denied"
60 if isinstance(exc, DjangoPermissionDenied):
61 response=Response({'detail': str(exc)}, status=status.HTTP_403_FORBIDDEN)
62 response.exception=True
63 return response
64 else:
65 return super(XOSRetrieveUpdateDestroyAPIView, self).handle_exception(exc)
66
67class XOSListCreateAPIView(generics.ListCreateAPIView):
68 def create(self, request, *args, **kwargs):
69 serializer = self.get_serializer(data=request.DATA, files=request.FILES)
70 if not (serializer.is_valid()):
71 response = {"error": "validation",
72 "specific_error": "not serializer.is_valid()",
73 "reasons": serializer.errors}
74 return Response(response, status=status.HTTP_400_BAD_REQUEST)
75
76 # now do XOS can_update permission checking
77
78 obj = serializer.object
79 obj.caller = request.user
80 if not obj.can_update(request.user):
81 response = {"error": "validation",
82 "specific_error": "failed can_update",
83 "reasons": []}
84 return Response(response, status=status.HTTP_400_BAD_REQUEST)
85
86 # stuff below is from generics.ListCreateAPIView
87
88 if (hasattr(self, "pre_save")):
89 # rest_framework 2.x
90 self.pre_save(serializer.object)
91 self.object = serializer.save(force_insert=True)
92 self.post_save(self.object, created=True)
93 else:
94 # rest_framework 3.x
95 self.perform_create(serializer)
96
97 headers = self.get_success_headers(serializer.data)
98 return Response(serializer.data, status=status.HTTP_201_CREATED,
99 headers=headers)
100
101 def handle_exception(self, exc):
102 # REST API drops the string attached to Django's PermissionDenied
103 # exception, and replaces it with a generic "Permission Denied"
104 if isinstance(exc, DjangoPermissionDenied):
105 response=Response({'detail': str(exc)}, status=status.HTTP_403_FORBIDDEN)
106 response.exception=True
107 return response
108 else:
109 return super(XOSListCreateAPIView, self).handle_exception(exc)
110