|
1 # -*- coding: utf-8 -*- |
|
2 ''' |
|
3 Created on Jul 01, 2014 |
|
4 |
|
5 @author: tc |
|
6 ''' |
|
7 from datetime import datetime |
|
8 import json |
|
9 import logging |
|
10 import uuid |
|
11 |
|
12 from django.core.urlresolvers import reverse |
|
13 from django.http import Http404 |
|
14 from django.http.response import HttpResponse, HttpResponseBadRequest |
|
15 from django.shortcuts import get_object_or_404, redirect |
|
16 from django.views.decorators.csrf import csrf_exempt |
|
17 from django.views.generic import View |
|
18 from renkanmanager.models import Renkan, Revision, Workspace |
|
19 from renkanmanager.permissions import CanEditRenkan, CanDeleteRenkan, CanCreateRenkan, \ |
|
20 CanEditWorkspace, CanDeleteWorkspace, CanCreateWorkspace, \ |
|
21 CanDeleteRevision |
|
22 from renkanmanager.serializers import RenkanSerializer, RevisionSerializer, WorkspaceSerializer |
|
23 from renkanmanager.auth import CsrfExemptSessionAuthentication |
|
24 from rest_framework import permissions, status |
|
25 from rest_framework.response import Response |
|
26 from rest_framework.views import APIView |
|
27 |
|
28 |
|
29 logger = logging.getLogger(__name__) |
|
30 |
|
31 class RenkanList(APIView): |
|
32 """ |
|
33 View for listing renkans or posting new renkan |
|
34 """ |
|
35 permission_classes = ( |
|
36 permissions.IsAuthenticatedOrReadOnly, |
|
37 CanCreateRenkan, |
|
38 ) |
|
39 |
|
40 def get(self, request, workspace_guid='', format=None): |
|
41 if workspace_guid == '': |
|
42 renkans = Renkan.objects.all() |
|
43 else: |
|
44 renkans = Renkan.objects.filter(workspace_guid=workspace_guid) |
|
45 serializer = RenkanSerializer(renkans, many=True) |
|
46 return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json') |
|
47 |
|
48 def post(self, request, workspace_guid='', format=None): |
|
49 create_data = request.data |
|
50 source_renkan_guid = request.GET.get("source_renkan_id", request.data.get("source_renkan_id", None)) |
|
51 source_revision_guid = request.GET.get("source_revision_id", request.data.get("source_revision_id", None)) |
|
52 if source_renkan_guid is not None: |
|
53 try: |
|
54 source_renkan=Renkan.objects.get(renkan_guid=source_renkan_guid) |
|
55 except Renkan.DoesNotExist: |
|
56 return Response({'detail': 'Source renkan '+source_renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) |
|
57 source_revision_guid = source_renkan.current_revision_guid |
|
58 if source_revision_guid is not None: |
|
59 try: |
|
60 source_revision=Revision.objects.get(revision_guid=source_revision_guid) |
|
61 except Revision.DoesNotExist: |
|
62 return Response({'detail': 'Source revision '+source_revision_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) |
|
63 create_data["source_revision_id"] = source_revision.revision_guid |
|
64 create_data["title"] = request.data.get("title", source_revision.title) |
|
65 create_data["content"] = source_revision.content |
|
66 if workspace_guid: |
|
67 try: |
|
68 workspace = Workspace.objects.get(workspace_guid=workspace_guid) |
|
69 except Workspace.DoesNotExist: |
|
70 return Response({'detail': 'Workspace '+workspace_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) |
|
71 create_data["workspace_id"] = workspace_guid |
|
72 |
|
73 serializer = RenkanSerializer(data=create_data) |
|
74 if serializer.is_valid(): |
|
75 serializer.save(creator=request.user) |
|
76 return Response(serializer.data, status=status.HTTP_201_CREATED, content_type='application/json') |
|
77 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) |
|
78 |
|
79 |
|
80 class RenkanDetail(APIView): |
|
81 """ |
|
82 View for retrieving, updating or deleting a single renkan |
|
83 """ |
|
84 lookup_field = "renkan_guid" |
|
85 permission_classes = ( |
|
86 permissions.IsAuthenticatedOrReadOnly, |
|
87 CanEditRenkan, |
|
88 CanDeleteRenkan, |
|
89 ) |
|
90 authentication_classes = ( |
|
91 CsrfExemptSessionAuthentication, |
|
92 ) |
|
93 @csrf_exempt |
|
94 def dispatch(self, *args, **kwargs): |
|
95 return super(RenkanDetail, self).dispatch(*args, **kwargs) |
|
96 |
|
97 def get_object(self, renkan_guid): |
|
98 return Renkan.objects.get(renkan_guid=renkan_guid) |
|
99 |
|
100 def get(self, request, renkan_guid, format=None): |
|
101 try: |
|
102 renkan = self.get_object(renkan_guid=renkan_guid) |
|
103 except Renkan.DoesNotExist: |
|
104 return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) |
|
105 self.check_object_permissions(request, renkan) |
|
106 serializer = RenkanSerializer(renkan) |
|
107 if {'true': True, 'false': False, "0": False, "1": True}.get(request.GET.get("content_only", "false").lower()): |
|
108 return Response(json.loads(serializer.data["content"]), status=status.HTTP_200_OK, content_type='application/json') |
|
109 return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json') |
|
110 |
|
111 def put(self, request, renkan_guid, format=None): |
|
112 try: |
|
113 renkan = self.get_object(renkan_guid=renkan_guid) |
|
114 except Renkan.DoesNotExist: |
|
115 return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) |
|
116 self.check_object_permissions(request, renkan) |
|
117 if {'true': True, 'false': False, "0": False, "1": True}.get(request.GET.get("content_only", "false").lower()): |
|
118 put_data = {} |
|
119 put_data["content"] = json.dumps(request.data) |
|
120 put_data["title"] = request.data.get("title", "") |
|
121 else: |
|
122 put_data = request.data |
|
123 serializer = RenkanSerializer(renkan, data=put_data) |
|
124 if serializer.is_valid(): |
|
125 serializer.save(updator=request.user) |
|
126 return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json') |
|
127 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) |
|
128 |
|
129 def delete(self, request, renkan_guid, format=None): |
|
130 try: |
|
131 to_delete_renkan = self.get_object(renkan_guid=renkan_guid) |
|
132 except Renkan.DoesNotExist: |
|
133 return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) |
|
134 self.check_object_permissions(request, to_delete_renkan) |
|
135 renkan_revisions = Revision.objects.filter(parent_renkan_guid = to_delete_renkan.renkan_guid) |
|
136 for child_revision in renkan_revisions: |
|
137 # Deleting reference to revision in renkans copied from this revision |
|
138 for related_renkan in Renkan.objects.filter(source_revision_guid=child_revision.revision_guid): |
|
139 related_renkan.source_revision_guid = '' |
|
140 related_renkan.save() |
|
141 child_revision.delete() |
|
142 to_delete_renkan.delete() |
|
143 return Response(status=status.HTTP_204_NO_CONTENT) |
|
144 |
|
145 class WorkspaceList(APIView): |
|
146 """ |
|
147 View for listing workspaces or creating new workspace |
|
148 """ |
|
149 permission_classes = ( |
|
150 permissions.IsAuthenticatedOrReadOnly, |
|
151 CanCreateWorkspace, |
|
152 ) |
|
153 |
|
154 def get(self, request, format=None): |
|
155 workspaces = Workspace.objects.all() |
|
156 serializer = WorkspaceSerializer(workspaces, many=True) |
|
157 return Response(serializer.data) |
|
158 |
|
159 def post(self, request, format=None): |
|
160 serializer = WorkspaceSerializer(data=request.data) |
|
161 if serializer.is_valid(): |
|
162 serializer.save(creator=request.user) |
|
163 return Response(serializer.data, status=status.HTTP_201_CREATED, content_type='application/json') |
|
164 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) |
|
165 |
|
166 class WorkspaceDetail(APIView): |
|
167 """ |
|
168 View for retrieving, updating or deleting a single workspace |
|
169 """ |
|
170 permission_classes = ( |
|
171 permissions.IsAuthenticatedOrReadOnly, |
|
172 CanEditWorkspace, |
|
173 CanDeleteWorkspace, |
|
174 ) |
|
175 |
|
176 def get_object(self, workspace_guid): |
|
177 return Workspace.objects.get(workspace_guid=workspace_guid) |
|
178 |
|
179 def get(self, request, workspace_guid, format=None): |
|
180 try: |
|
181 workspace = Workspace.objects.get(workspace_guid=workspace_guid) |
|
182 except Workspace.DoesNotExist: |
|
183 return Response({'detail': 'Workspace '+workspace_guid+' does not exist.'}, status=status.HTTP_404_NOT_FOUND) |
|
184 self.check_object_permissions(request, workspace) |
|
185 serializer = WorkspaceSerializer(workspace) |
|
186 return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json') |
|
187 |
|
188 def put(self, request, workspace_guid, format=None): |
|
189 try: |
|
190 workspace = Workspace.objects.get(workspace_guid=workspace_guid) |
|
191 except Workspace.DoesNotExist: |
|
192 return Response({'detail': 'Workspace '+workspace_guid+' does not exist.'}, status=status.HTTP_404_NOT_FOUND) |
|
193 self.check_object_permissions(request, workspace) |
|
194 serializer = WorkspaceSerializer(workspace, data=request.data) |
|
195 if serializer.is_valid(): |
|
196 serializer.save() |
|
197 return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json') |
|
198 return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) |
|
199 |
|
200 def delete(self, request, workspace_guid, format=None): |
|
201 try: |
|
202 to_delete_workspace = self.get_object(workspace_guid=workspace_guid) |
|
203 except Workspace.DoesNotExist: |
|
204 return Response({'detail': 'Workspace '+workspace_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) |
|
205 self.check_object_permissions(request, to_delete_workspace) |
|
206 if to_delete_workspace.renkan_count != 0: |
|
207 return Response({'detail': 'Workspace '+workspace_guid+' cannot be deleted because it is not empty'}, status=status.HTTP_400_BAD_REQUEST) |
|
208 to_delete_workspace.delete() |
|
209 return Response(status=status.HTTP_204_NO_CONTENT) |
|
210 |
|
211 class RevisionList(APIView): |
|
212 """ |
|
213 View for listing revisions from a given renkan |
|
214 """ |
|
215 permission_classes = (permissions.IsAuthenticatedOrReadOnly,) |
|
216 |
|
217 def get_queryset(self, renkan_guid): |
|
218 return Revision.objects.filter(parent_renkan_guid=renkan_guid) |
|
219 |
|
220 def get(self, request, renkan_guid, format=None): |
|
221 revisions = self.get_queryset(renkan_guid) |
|
222 if not revisions: |
|
223 return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) |
|
224 serializer = RevisionSerializer(revisions.all(), many=True) |
|
225 return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json') |
|
226 |
|
227 class RevisionDetail(APIView): |
|
228 """ |
|
229 View for retrieving or deleting a single revision from a given renkan |
|
230 """ |
|
231 permission_classes = ( |
|
232 permissions.IsAuthenticatedOrReadOnly, |
|
233 CanDeleteRevision, |
|
234 ) |
|
235 |
|
236 def get_queryset(self, renkan_guid): |
|
237 return Revision.objects.filter(parent_renkan_guid=renkan_guid) |
|
238 |
|
239 def get(self, request, renkan_guid, revision_guid, format=None): |
|
240 revisions = self.get_queryset(renkan_guid) |
|
241 if not revisions: |
|
242 return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) |
|
243 try: |
|
244 revision = revisions.get(revision_guid=revision_guid) |
|
245 except Revision.DoesNotExist: |
|
246 return Response({'detail': 'Revision '+revision_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) |
|
247 self.check_object_permissions(request, revision) |
|
248 serializer = RevisionSerializer(revision) |
|
249 return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json') |
|
250 |
|
251 def delete(self, request, renkan_guid, revision_guid, format=None): |
|
252 revisions = self.get_queryset(renkan_guid) |
|
253 if not revisions: |
|
254 return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) |
|
255 try: |
|
256 revision = revisions.get(revision_guid=revision_guid) |
|
257 except Revision.DoesNotExist: |
|
258 return Response({'detail': 'Revision '+revision_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) |
|
259 self.check_object_permissions(request, revision) |
|
260 if revisions.count() == 1: |
|
261 return Response({'detail': 'You cannot delete the last remaining revision of a renkan from the Revision API. Try deleting the parent Renkan with the Renkan API'}, status=status.HTTP_400_BAD_REQUEST) |
|
262 if revision.is_current_revision: |
|
263 return Response({'detail': 'You cannot delete the current revision of a renkan from the Revision API.'}, status=status.HTTP_400_BAD_REQUEST) |
|
264 |
|
265 # Deleting reference to revision in renkans copied from this revision |
|
266 for related_renkan in Renkan.objects.filter(source_revision_guid=revision_guid): |
|
267 related_renkan.source_revision_guid = '' |
|
268 related_renkan.save() |
|
269 revision.delete() |
|
270 return Response(status=status.HTTP_204_NO_CONTENT) |