# HG changeset patch # User durandn # Date 1465289081 -7200 # Node ID f0f07e2b841f5f1748371fb3362f5fd5cb34d742 # Parent b9edc1c1538aaa9420d55ae066134078f56771ef serverside: translation + timestamp handling + logging diff -r b9edc1c1538a -r f0f07e2b841f server/python/django2/renkanmanager/api/views.py --- a/server/python/django2/renkanmanager/api/views.py Tue May 03 14:32:28 2016 +0200 +++ b/server/python/django2/renkanmanager/api/views.py Tue Jun 07 10:44:41 2016 +0200 @@ -87,7 +87,7 @@ try: renkan = self.get_object(renkan_guid=renkan_guid) except Renkan.DoesNotExist: - return Response({'detail': 'Renkan project %r does not exist'.format(renkan_guid)}, status=status.HTTP_404_NOT_FOUND) + return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) self.check_object_permissions(request, renkan) serializer = RenkanSerializer(renkan) if {'true': True, 'false': False, "0": False, "1": True}.get(request.GET.get("content_only", "false").lower()): @@ -98,7 +98,7 @@ try: renkan = self.get_object(renkan_guid=renkan_guid) except Renkan.DoesNotExist: - return Response({'detail': 'Renkan project %r does not exist'.format(renkan_guid)}, status=status.HTTP_404_NOT_FOUND) + return Response({'detail': 'Renkan project '+renkan_guid+' does not exist'}, status=status.HTTP_404_NOT_FOUND) logger.debug("RENKAN PUT %r : CHECKING OBJECT PERMISSION", renkan_guid) logger.debug("RENKAN PUT: permission? %r", request.user.has_perm("change_renkan", renkan)) self.check_object_permissions(request, renkan) @@ -109,9 +109,13 @@ put_data["title"] = request.data.get("title", "") else: put_data = request.data + if put_data.get("validation_timestamp", None) is None and put_data.get("content", None) is not None: + put_data["validation_timestamp"] = json.loads(put_data["content"]).get("updated", "") serializer = RenkanSerializer(renkan, data=put_data) if serializer.is_valid(): serializer.save(updator=request.user) + if {'true': True, 'false': False, "0": False, "1": True}.get(request.GET.get("content_only", "false").lower()): + return Response(json.loads(serializer.data["content"]), status=status.HTTP_200_OK, content_type='application/json') return Response(serializer.data, status=status.HTTP_200_OK, content_type='application/json') return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) diff -r b9edc1c1538a -r f0f07e2b841f server/python/django2/renkanmanager/models.py --- a/server/python/django2/renkanmanager/models.py Tue May 03 14:32:28 2016 +0200 +++ b/server/python/django2/renkanmanager/models.py Tue Jun 07 10:44:41 2016 +0200 @@ -9,6 +9,7 @@ from django.db import models, transaction from django.core.exceptions import ValidationError from django.utils import timezone, dateparse +from django.utils.translation import ugettext_lazy as _ @@ -120,6 +121,12 @@ else: return '' + def __unicode__(self): + return self.renkan_guid + + def __str__(self): + return self.renkan_guid + @transaction.atomic def save_renkan(self, updator, timestamp="", title="", content="", create_new_revision=False): """ @@ -128,7 +135,7 @@ """ if (not timestamp) or ((self.current_revision is not None) and dateparse.parse_datetime(timestamp) < self.current_revision.modification_date): logger.error("SAVING RENKAN: provided timestamp is %r, which isn't current revision modification_date %r", timestamp, self.current_revision.modification_date) - raise ValidationError(message="Error saving Renkan: provided timestamp isn't current revision modification_date") + raise ValidationError(_("Cannot save, provided timestamp is invalid")) else: dt_timestamp = dateparse.parse_datetime(timestamp) self.save() diff -r b9edc1c1538a -r f0f07e2b841f server/python/django2/renkanmanager/serializers.py --- a/server/python/django2/renkanmanager/serializers.py Tue May 03 14:32:28 2016 +0200 +++ b/server/python/django2/renkanmanager/serializers.py Tue Jun 07 10:44:41 2016 +0200 @@ -1,11 +1,14 @@ -import json, uuid, datetime, time +import json, logging, uuid, datetime, time from django.db import transaction from django.contrib.auth import get_user_model from django.conf import settings +from django.core.exceptions import ValidationError +from django.utils import dateparse from renkanmanager.models import Renkan, Workspace, Revision from rest_framework import serializers +logger = logging.getLogger(__name__) RENKAN_USER_DISPLAY_FIELD = getattr(settings, "RENKAN_USER_DISPLAY_FIELD", get_user_model().USERNAME_FIELD) class RenkanSerializer(serializers.Serializer): @@ -66,6 +69,8 @@ validation_timestamp = validated_data.get('validation_timestamp') else: validation_timestamp = json.loads(content).get("updated", "") + if dateparse.parse_datetime(validation_timestamp) < renkan.current_revision.modification_date: + raise serializers.ValidationError("Provided timestamp is invalid") if title != json.loads(content).get("title", ""): content_dict = json.loads(content) content_dict["title"] = title @@ -73,7 +78,7 @@ try: renkan.save_renkan(updator=updator, timestamp=validation_timestamp, title=title, content=content, create_new_revision=create_new_revision) except ValidationError as ve: - raise serializers.ValidationError(ve.args[0]) + raise serializers.ValidationError(str(ve.args[0])) return renkan def validate_workspace_id(self, value): @@ -88,20 +93,22 @@ def validate_content(self, value): try: - json.loads(value) + loaded_json = json.loads(value) except ValueError: raise serializers.ValidationError("Content format is not a JSON-serializable") - loaded_json = json.loads(value) - if (not "nodes" in loaded_json): raise serializers.ValidationError("Content requires a 'nodes' entry") if (not "edges" in loaded_json): raise serializers.ValidationError("Content requires a 'edges' entry") if (not "views" in loaded_json): raise serializers.ValidationError("Content requires a 'views' entry") - return value - + + def validate_validation_timestamp(self, value): + logger.debug("%r", value) + if self.instance and dateparse.parse_datetime(value) < self.get_current_revision_modification_date(self.instance): + raise serializers.ValidationError("Invalid timestamp was provided") + return value class RevisionSerializer(serializers.Serializer): id = serializers.ReadOnlyField(source="revision_guid")