Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move constraint validations and their stuff into core #269

Merged
merged 1 commit into from
Jan 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 80 additions & 0 deletions core/serializers.py
Original file line number Diff line number Diff line change
@@ -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):
Expand Down Expand Up @@ -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
67 changes: 8 additions & 59 deletions prizetap/serializers.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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__"
Expand 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"]
Expand All @@ -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)


Expand Down