Add submit_id to signup model
This commit is contained in:
@@ -0,0 +1,65 @@
|
|||||||
|
# Generated by Django 4.2.24 on 2025-10-13 14:48
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("kaehmy", "0011_delete_kaehmybaserole"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="baserole",
|
||||||
|
name="category",
|
||||||
|
field=models.CharField(
|
||||||
|
choices=[
|
||||||
|
("board", "Board"),
|
||||||
|
("corporate", "Corporate affairs"),
|
||||||
|
("freshman", "Freshmen"),
|
||||||
|
("international", "International"),
|
||||||
|
("siwa", "SIK's free time"),
|
||||||
|
("media", "Media"),
|
||||||
|
("tech", "Technology"),
|
||||||
|
("wellbeing", "Wellbeing"),
|
||||||
|
("sikpaja", "Sik-paja"),
|
||||||
|
("ceremonies", "Ceremonies"),
|
||||||
|
("studies", "Studies"),
|
||||||
|
("sosso", "Sössö magazine"),
|
||||||
|
("pota", "PoTa"),
|
||||||
|
("alumni", "Alumni relations"),
|
||||||
|
("n", "N"),
|
||||||
|
("others", "Others"),
|
||||||
|
],
|
||||||
|
default="others",
|
||||||
|
max_length=255,
|
||||||
|
verbose_name="Category",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="customrole",
|
||||||
|
name="baserole_ptr",
|
||||||
|
field=models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="kaehmy.baserole",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="presetrole",
|
||||||
|
name="baserole_ptr",
|
||||||
|
field=models.OneToOneField(
|
||||||
|
auto_created=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
parent_link=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
to="kaehmy.baserole",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# Generated by Django 4.2.24 on 2025-10-13 14:48
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("contenttypes", "0002_remove_content_type_name"),
|
||||||
|
("webapp", "0082_delete_baserole"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="signup",
|
||||||
|
name="submit_id",
|
||||||
|
field=models.UUIDField(default=uuid.uuid4, editable=False, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="basewebhook",
|
||||||
|
name="polymorphic_ctype",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
editable=False,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name="polymorphic_%(app_label)s.%(class)s_set+",
|
||||||
|
to="contenttypes.contenttype",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.24 on 2025-10-13 15:19
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0083_signup_submit_id_alter_basewebhook_polymorphic_ctype"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="signup",
|
||||||
|
name="submit_id",
|
||||||
|
field=models.UUIDField(null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.24 on 2025-10-13 15:46
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0084_alter_signup_submit_id"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="signup",
|
||||||
|
name="submit_id",
|
||||||
|
field=models.CharField(null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.24 on 2025-10-13 15:51
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0085_alter_signup_submit_id"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="signup",
|
||||||
|
name="submit_id",
|
||||||
|
field=models.UUIDField(editable=False, null=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
# Generated by Django 4.2.24 on 2025-10-13 15:53
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("webapp", "0086_alter_signup_submit_id"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name="signup",
|
||||||
|
name="submit_id",
|
||||||
|
field=models.UUIDField(editable=False, null=True, unique=True),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -195,6 +195,8 @@ class Signup(models.Model):
|
|||||||
email = models.EmailField(blank=True, null=True)
|
email = models.EmailField(blank=True, null=True)
|
||||||
# Random unique identifier. Used for signup editing by the user.
|
# Random unique identifier. Used for signup editing by the user.
|
||||||
uuid = models.UUIDField(default=uuid4, editable=False)
|
uuid = models.UUIDField(default=uuid4, editable=False)
|
||||||
|
# Random unique identifier generated by browser upon opening signup form. Used to prevent duplicate signups.
|
||||||
|
submit_id = models.UUIDField(null=True, editable=False, unique=True)
|
||||||
deleted = models.BooleanField(default=False)
|
deleted = models.BooleanField(default=False)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ class SignupSerializer(serializers.ModelSerializer):
|
|||||||
source="signupForm", queryset=SignupForm.objects.all()
|
source="signupForm", queryset=SignupForm.objects.all()
|
||||||
)
|
)
|
||||||
list_name = serializers.CharField(read_only=True)
|
list_name = serializers.CharField(read_only=True)
|
||||||
|
submit_id = serializers.UUIDField(required=False)
|
||||||
|
|
||||||
def add_extra_fields(self, validated_data):
|
def add_extra_fields(self, validated_data):
|
||||||
questions = validated_data["signupForm"].questions
|
questions = validated_data["signupForm"].questions
|
||||||
@@ -34,7 +35,7 @@ class SignupSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Signup
|
model = Signup
|
||||||
fields = ("id", "signupForm_id", "answer", "list_name")
|
fields = ("id", "submit_id", "signupForm_id", "answer", "list_name")
|
||||||
extra_kwargs = {
|
extra_kwargs = {
|
||||||
"url": {
|
"url": {
|
||||||
"view_name": "signup-detail",
|
"view_name": "signup-detail",
|
||||||
|
|||||||
+5
-29
@@ -12,6 +12,7 @@ from django.views.decorators.http import require_http_methods
|
|||||||
from django_filters import rest_framework as filters
|
from django_filters import rest_framework as filters
|
||||||
from django.db.models import Prefetch
|
from django.db.models import Prefetch
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
|
from django.db.utils import IntegrityError
|
||||||
from rest_framework import routers
|
from rest_framework import routers
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
|
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
|
||||||
@@ -201,29 +202,6 @@ class SignupViewSet(ModelViewSet):
|
|||||||
serializer_class = SignupSerializer
|
serializer_class = SignupSerializer
|
||||||
permission_classes = [SignupPermission]
|
permission_classes = [SignupPermission]
|
||||||
|
|
||||||
submit_keys = (
|
|
||||||
{}
|
|
||||||
) # Dictionary for currently invalid submission keys; {key: timestamp}
|
|
||||||
|
|
||||||
def key_is_unique(self, submitKey):
|
|
||||||
current_time = time.time()
|
|
||||||
print("Checking", submitKey)
|
|
||||||
# Remove expired keys from dict (older than 1 h)
|
|
||||||
# A key that expires as the function is called is considered valid
|
|
||||||
print("Keys", SignupViewSet.submit_keys)
|
|
||||||
SignupViewSet.submit_keys = {
|
|
||||||
key: time
|
|
||||||
for key, time in SignupViewSet.submit_keys.items()
|
|
||||||
if time + 3600 >= current_time
|
|
||||||
}
|
|
||||||
print("After", SignupViewSet.submit_keys)
|
|
||||||
if submitKey not in SignupViewSet.submit_keys: # Key is unique; valid
|
|
||||||
SignupViewSet.submit_keys[submitKey] = current_time
|
|
||||||
return True
|
|
||||||
else: # Key is not unique; invalid, refresh timestamp
|
|
||||||
SignupViewSet.submit_keys[submitKey] = current_time
|
|
||||||
return False
|
|
||||||
|
|
||||||
@action(detail=True, methods=["get", "put"], permission_classes=[AllowAny])
|
@action(detail=True, methods=["get", "put"], permission_classes=[AllowAny])
|
||||||
def edit(self, request, pk=None, *args, **kwargs):
|
def edit(self, request, pk=None, *args, **kwargs):
|
||||||
uuid = request.query_params.get("uuid", None)
|
uuid = request.query_params.get("uuid", None)
|
||||||
@@ -238,12 +216,6 @@ class SignupViewSet(ModelViewSet):
|
|||||||
def create(self, request, *args, **kwargs):
|
def create(self, request, *args, **kwargs):
|
||||||
id = request.data["signupForm_id"]
|
id = request.data["signupForm_id"]
|
||||||
try:
|
try:
|
||||||
submitKey = request.data.get("submitKey")
|
|
||||||
if submitKey is not None and not self.key_is_unique(submitKey):
|
|
||||||
return JsonResponse(
|
|
||||||
status=200, data={"message": "Ignored repeated request"}
|
|
||||||
)
|
|
||||||
|
|
||||||
answer = request.data["answer"]
|
answer = request.data["answer"]
|
||||||
form = SignupForm.objects.get(id=id)
|
form = SignupForm.objects.get(id=id)
|
||||||
if form.isOpen:
|
if form.isOpen:
|
||||||
@@ -256,6 +228,10 @@ class SignupViewSet(ModelViewSet):
|
|||||||
return JsonResponse(
|
return JsonResponse(
|
||||||
status=404, data={"error": f"SignupForm {id} not found"}
|
status=404, data={"error": f"SignupForm {id} not found"}
|
||||||
)
|
)
|
||||||
|
except IntegrityError:
|
||||||
|
return JsonResponse(
|
||||||
|
status=200, data={"message": "The submission had already been received"}
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
return JsonResponse(
|
return JsonResponse(
|
||||||
status=404, data={"error": f"SignupForm {id} not found"}
|
status=404, data={"error": f"SignupForm {id} not found"}
|
||||||
|
|||||||
Reference in New Issue
Block a user