diff --git a/core/serializers.py b/core/serializers.py index 18848f5a..c822bc64 100644 --- a/core/serializers.py +++ b/core/serializers.py @@ -1,8 +1,13 @@ +import base64 +import json + +from django.core.validators import FileExtensionValidator from rest_framework import serializers from core.constraints import ConstraintVerification, get_constraint from .models import Chain, UserConstraint +from .utils import UploadFileStorage class ChainSerializer(serializers.ModelSerializer): @@ -65,3 +70,78 @@ class Meta: def get_params(self, constraint: UserConstraint): c_class: ConstraintVerification = get_constraint(constraint.name) return [p.name for p in c_class.param_keys()] + + +class ConstraintProviderSerializer(serializers.Serializer): + constraint_files = serializers.ListField( + required=False, + child=serializers.FileField( + allow_empty_file=False, validators=[FileExtensionValidator(["csv"])] + ), + ) + + class Meta: + abstract = True + + def validate(self, data): + constraints = data["constraints"] + if "constraint_params" in data: + data["constraint_params"] = base64.b64decode( + data["constraint_params"] + ).decode("utf-8") + else: + data["constraint_params"] = "{}" + constraint_params = json.loads(data["constraint_params"]) + reversed_constraints = [] + if "reversed_constraints" in data: + reversed_constraints = str(data["reversed_constraints"]).split(",") + if len(constraints) != 0: + for c in constraints: + constraint_class: ConstraintVerification = get_constraint(c.name) + try: + if len(constraint_class.param_keys()) != 0: + constraint_class.is_valid_param_keys(constraint_params[c.name]) + except KeyError as e: + # TODO: revise errors + raise serializers.ValidationError( + {"constraint_params": [{f"{c.name}": str(e)}]} + ) + valid_constraints = [str(c.pk) for c in constraints] + for c in reversed_constraints: + if c not in valid_constraints: + raise serializers.ValidationError( + {"reversed_constraints": [{f"{c}": "Invalid constraint pk"}]} + ) + if "constraint_files" in data: + file_names = [file.name for file in data["constraint_files"]] + if len(file_names) != len(set(file_names)): + raise serializers.ValidationError( + {"constraint_files": "The name of files should be unique"} + ) + return data + + def save_constraint_files(self, validated_data): + if "constraint_files" in validated_data: + constraint_files = validated_data.pop("constraint_files") + constraint_params = json.loads(validated_data.get("constraint_params")) + file_storage = UploadFileStorage() + for ـ, constraint in constraint_params.items(): + if "CSV_FILE" not in constraint: + continue + file_exist = False + for file in constraint_files: + if constraint["CSV_FILE"] == file.name: + path = file_storage.save(file) + constraint["CSV_FILE"] = path + file_exist = True + break + if not file_exist: + raise serializers.ValidationError( + { + "constraint_files": ( + f'File {constraint["CSV_FILE"]} is not exist' + ) + } + ) + validated_data["constraint_params"] = json.dumps(constraint_params) + return validated_data diff --git a/prizetap/serializers.py b/prizetap/serializers.py index 3db50f1e..b31518b0 100644 --- a/prizetap/serializers.py +++ b/prizetap/serializers.py @@ -1,13 +1,12 @@ -import base64 -import json - -from django.core.validators import FileExtensionValidator from rest_framework import serializers from authentication.serializers import SimpleProfilerSerializer from core.constraints import ConstraintVerification, get_constraint -from core.serializers import ChainSerializer, UserConstraintBaseSerializer -from core.utils import UploadFileStorage +from core.serializers import ( + ChainSerializer, + ConstraintProviderSerializer, + UserConstraintBaseSerializer, +) from .constants import CONTRACT_ADDRESSES from .models import Constraint, LineaRaffleEntries, Raffle, RaffleEntry, UserConstraint @@ -95,14 +94,7 @@ class Meta: ] -class CreateRaffleSerializer(serializers.ModelSerializer): - constraint_files = serializers.ListField( - required=False, - child=serializers.FileField( - allow_empty_file=False, validators=[FileExtensionValidator(["csv"])] - ), - ) - +class CreateRaffleSerializer(serializers.ModelSerializer, ConstraintProviderSerializer): class Meta: model = Raffle fields = "__all__" @@ -118,38 +110,7 @@ class Meta: ] def validate(self, data): - constraints = data["constraints"] - constraint_params = json.loads(base64.b64decode(data["constraint_params"])) - data["constraint_params"] = base64.b64decode(data["constraint_params"]).decode( - "utf-8" - ) - reversed_constraints = [] - if "reversed_constraints" in data: - reversed_constraints = str(data["reversed_constraints"]).split(",") - if len(constraints) != 0: - for c in constraints: - constraint_class: ConstraintVerification = get_constraint(c.name) - try: - if len(constraint_class.param_keys()) != 0: - constraint_class.is_valid_param_keys(constraint_params[c.name]) - except KeyError as e: - # TODO: revise errors - raise serializers.ValidationError( - {"constraint_params": [{f"{c.name}": str(e)}]} - ) - valid_constraints = [str(c.pk) for c in constraints] - if len(reversed_constraints) > 0: - for c in reversed_constraints: - if c not in valid_constraints: - raise serializers.ValidationError( - {"reversed_constraints": [{f"{c}": "Invalid constraint pk"}]} - ) - if "constraint_files" in data: - file_names = [file.name for file in data["constraint_files"]] - if len(file_names) != len(set(file_names)): - raise serializers.ValidationError( - {"constraint_files": "The name of files should be unique"} - ) + data = super().validate(data) if ( "winners_count" in data and data["winners_count"] > data["max_number_of_entries"] @@ -173,19 +134,7 @@ def validate(self, data): return data def create(self, validated_data): - if "constraint_files" in validated_data: - constraint_files = validated_data.pop("constraint_files") - constraint_params = json.loads(validated_data.get("constraint_params")) - file_storage = UploadFileStorage() - for key, constraint in constraint_params.items(): - if "CSV_FILE" not in constraint: - continue - for file in constraint_files: - if constraint["CSV_FILE"] == file.name: - path = file_storage.save(file) - constraint["CSV_FILE"] = path - break - validated_data["constraint_params"] = json.dumps(constraint_params) + validated_data = self.save_constraint_files(validated_data) return super().create(validated_data)