Skip to content
Snippets Groups Projects

Refactor update creation api

Merged Samuel GAIST requested to merge refactor_update_creation_api into master
All threads resolved!
1 file
+ 7
23
Compare changes
  • Side-by-side
  • Inline
@@ -25,24 +25,28 @@
# #
###############################################################################
import copy
import simplejson as json
import difflib
from django.conf import settings
from django.contrib.auth.models import User
from django.utils import six
from django.db.models import CharField, Value as V
from django.db.models.functions import Concat
from rest_framework import serializers
from rest_framework import exceptions as drf_exceptions
from ..team.models import Team
from ..common.utils import ensure_html
from ..common.utils import annotate_full_name
from ..common.utils import validate_restructuredtext
from ..common import fields as beat_fields
from .models import Shareable, Versionable, Contribution
from .exceptions import ContributionCreationError
from .fields import JSONSerializerField, StringListField
import simplejson as json
import difflib
from . import fields as serializer_fields
# ----------------------------------------------------------
@@ -83,8 +87,8 @@ class CheckNameSerializer(serializers.Serializer):
class SharingSerializer(serializers.Serializer):
users = StringListField(required=False)
teams = StringListField(required=False)
users = serializer_fields.StringListField(required=False)
teams = serializer_fields.StringListField(required=False)
def validate_users(self, users):
user_accounts = User.objects.filter(username__in=users).values_list(
@@ -297,24 +301,80 @@ class ContributionSerializer(VersionableSerializer):
# ----------------------------------------------------------
class ContributionCreationSerializer(serializers.ModelSerializer):
declaration = JSONSerializerField(required=False)
class ContributionModSerializer(serializers.ModelSerializer):
declaration = beat_fields.JSONField(required=False)
description = serializers.CharField(required=False, allow_blank=True)
fork_of = serializers.JSONField(required=False)
class Meta:
fields = ["short_description", "description", "declaration"]
beat_core_class = None
def validate_description(self, description):
if description.find("\\") >= 0: # was escaped, unescape
description = description.decode("string_escape")
validate_restructuredtext(description)
return description
def validate_declaration(self, declaration):
decl = copy.deepcopy(declaration)
obj = self.Meta.beat_core_class(prefix=settings.PREFIX, data=decl)
if not obj.valid:
raise drf_exceptions.ValidationError(obj.errors)
return declaration
def update(self, instance, validated_data):
declaration = validated_data.get("declaration")
if declaration is not None and not instance.modifiable():
raise drf_exceptions.PermissionDenied(
"The {} isn't modifiable anymore (either shared with someone else, or needed by an attestation)".format(
self.Meta.model.__name__.lower()
)
)
return super().update(instance, validated_data)
def filter_representation(self, representation):
"""Filter out fields if given in query parameters"""
request = self.context["request"]
fields = request.query_params.get("fields", None)
if fields is not None:
fields = fields.split(",")
to_remove = [key for key in representation.keys() if key not in fields]
for key in to_remove:
representation.pop(key)
# Retrieve the description in HTML format
if "html_description" in fields:
description = self.instance.description
if len(description) > 0:
representation["html_description"] = ensure_html(description)
else:
representation["html_description"] = ""
return representation
def to_representation(self, instance):
representation = super().to_representation(instance)
return self.filter_representation(representation)
# ----------------------------------------------------------
class ContributionCreationSerializer(ContributionModSerializer):
fork_of = serializers.CharField(required=False)
previous_version = serializers.CharField(required=False)
version = serializers.IntegerField(min_value=1)
class Meta:
fields = [
class Meta(ContributionModSerializer.Meta):
fields = ContributionModSerializer.Meta.fields + [
"name",
"short_description",
"description",
"declaration",
"previous_version",
"fork_of",
"version",
]
beat_core_class = None
def validate_fork_of(self, fork_of):
if "previous_version" in self.initial_data:
@@ -330,25 +390,23 @@ class ContributionCreationSerializer(serializers.ModelSerializer):
)
return previous_version
def validate_description(self, description):
if description.find("\\") >= 0: # was escaped, unescape
description = description.decode("string_escape")
return description
def validate(self, data):
user = self.context.get("user")
name = self.Meta.model.sanitize_name(data["name"])
data["name"] = name
version = data.get("version")
def validate_version(self, version):
# If version is not one then it's necessarily a new version
# forks start at one
if version > 1 and "previous_version" not in data:
if version > 1 and "previous_version" not in self.initial_data:
name = self.initial_data["name"]
raise serializers.ValidationError(
"{} {} version {} incomplete history data posted".format(
self.Meta.model.__name__.lower(), name, version
)
)
return version
def validate(self, data):
user = self.context.get("user")
name = self.Meta.model.sanitize_name(data["name"])
data["name"] = name
version = data.get("version")
if self.Meta.model.objects.filter(
author=user, name=name, version=version
@@ -364,16 +422,9 @@ class ContributionCreationSerializer(serializers.ModelSerializer):
if previous_version is not None:
try:
previous_object = self.Meta.model.objects.annotate(
fullname=Concat(
"author__username",
V("/"),
"name",
V("/"),
"version",
output_field=CharField(),
)
).get(fullname=previous_version)
previous_object = annotate_full_name(self.Meta.model.objects).get(
full_name=previous_version
)
except self.Meta.model.DoesNotExist:
raise serializers.ValidationError(
"{} '{}' not found".format(
@@ -398,16 +449,9 @@ class ContributionCreationSerializer(serializers.ModelSerializer):
raise serializers.ValidationError("A fork starts at 1")
try:
forked_of_object = self.Meta.model.objects.annotate(
fullname=Concat(
"author__username",
V("/"),
"name",
V("/"),
"version",
output_field=CharField(),
)
).get(fullname=fork_of)
forked_of_object = annotate_full_name(self.Meta.model.objects).get(
full_name=fork_of
)
except self.Meta.model.DoesNotExist:
raise serializers.ValidationError(
"{} '{}' fork origin not found".format(
Loading