Merge branch 'feature/signup-improvements' into 'develop'
Feature/signup improvements See merge request sahkoinsinoorikilta/vtmk/web2.0-backend!31
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 2.1.5 on 2020-11-07 18:00
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('webapp', '0073_auto_20201107_1916'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='signup',
|
||||
name='deleted',
|
||||
field=models.BooleanField(default=False),
|
||||
),
|
||||
]
|
||||
+3
-3
@@ -115,7 +115,7 @@ class SignupForm(models.Model):
|
||||
|
||||
@property
|
||||
def signups(self):
|
||||
return Signup.objects.filter(signupForm=self).order_by('pk')
|
||||
return Signup.objects.filter(signupForm=self, deleted=False).order_by('pk')
|
||||
|
||||
@property
|
||||
def isOpen(self):
|
||||
@@ -125,7 +125,7 @@ class SignupForm(models.Model):
|
||||
|
||||
class Signup(models.Model):
|
||||
"""
|
||||
In
|
||||
Actual signup into any SignupForm. Deletes are soft.
|
||||
"""
|
||||
|
||||
class Meta:
|
||||
@@ -140,6 +140,7 @@ class Signup(models.Model):
|
||||
email = models.EmailField(blank=True, null=True)
|
||||
# Random unique identifier. Used for signup editing by the user.
|
||||
uuid = models.UUIDField(default=uuid4, editable=False)
|
||||
deleted = models.BooleanField(default=False)
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.signupForm}: {self.list_name} ({self.pk})"
|
||||
@@ -147,7 +148,6 @@ class Signup(models.Model):
|
||||
|
||||
@receiver(post_save, sender=Signup)
|
||||
def email_on_signup(sender, instance, created, **kwargs):
|
||||
"""Send email validation."""
|
||||
if created and instance.email:
|
||||
# TODO: Possible bug due to many-to-many relationship with events and forms.
|
||||
# TODO: Subject field crashes with lazy loaded translations.
|
||||
|
||||
@@ -40,14 +40,15 @@ CBOX_SCHEMA = {
|
||||
}
|
||||
|
||||
|
||||
def createSignupForm(name="Form1", start_time=timezone.now(), end_time=month_from_now(), questions=ALL_QUESTION_TYPES, schema=ALL_QUESTIONS_SCHEMA, visible=True):
|
||||
def createSignupForm(name="Form1", start_time=timezone.now(), end_time=month_from_now(), questions=ALL_QUESTION_TYPES, schema=ALL_QUESTIONS_SCHEMA, visible=True, quota=1):
|
||||
return SignupForm.objects.create(
|
||||
title=name,
|
||||
start_time=start_time,
|
||||
end_time=end_time,
|
||||
questions=questions,
|
||||
visible=visible,
|
||||
schema=schema
|
||||
schema=schema,
|
||||
quota=quota
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -56,16 +56,44 @@ class SignupTestCase(APITestCase):
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
self.assertEqual(Signup.objects.count(), 3)
|
||||
|
||||
def test_delete_as_admin(self):
|
||||
id = self.signup1.id
|
||||
no_auth_response = self.client.delete(f"{URL}{id}/", format="json")
|
||||
self.assertEqual(no_auth_response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
response = self.client.delete(f"{URL}{id}/", format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(Signup.objects.get(id=id).deleted, True)
|
||||
|
||||
@skip("NotImplemented")
|
||||
def test_get_hidden_forms_admin(self):
|
||||
pass
|
||||
|
||||
# Update and Delete are available for super admin (Django Admin)
|
||||
# and to the user that signed up (uid token)
|
||||
@skip("NotImplemented")
|
||||
def test_update_signup_token(self):
|
||||
pass
|
||||
id = self.signup1.id
|
||||
uuid = self.signup1.uuid
|
||||
clone = ALL_QUESTION_TYPES_ANSWER.copy()
|
||||
clone["-naY2R1-h"] = "Edited Testi"
|
||||
new = createSignupRequest("asd", self.signupForm.id, clone)
|
||||
response = self.client.put(f"{URL}{id}/edit/?uuid={uuid}", new, format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_200_OK)
|
||||
self.assertEqual(Signup.objects.get(id=id).answer["-naY2R1-h"], "Edited Testi")
|
||||
|
||||
@skip("NotImplemented")
|
||||
def test_delete_signup_token(self):
|
||||
pass
|
||||
|
||||
# TODO: Use some mocking library and check that mailjet is actually called
|
||||
def test_signupee_sendemail(self):
|
||||
form = self.signupForm
|
||||
emailURL = f"/api/signupForm/{form.id}/sendemail/"
|
||||
payload = {
|
||||
"subject": "Email subject",
|
||||
"content": "Markdown",
|
||||
"mode": "actual"
|
||||
}
|
||||
no_auth_response = self.client.post(emailURL, payload, format="json")
|
||||
self.assertEqual(no_auth_response.status_code, status.HTTP_401_UNAUTHORIZED)
|
||||
self.client.force_authenticate(user=self.authClient)
|
||||
response = self.client.post(emailURL, payload, format="json")
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
@@ -55,6 +55,10 @@ def month_from_now():
|
||||
|
||||
def send_email(to, subject, body, html=False):
|
||||
if not ENABLE_AUTOMATIC_EMAILS:
|
||||
logging.debug("Skipping email")
|
||||
logging.debug(f"to: {to}")
|
||||
logging.debug(f"subject: {subject}")
|
||||
logging.debug(f"body: {body}")
|
||||
return
|
||||
try:
|
||||
mailjet = Client(auth=(EMAIL_API_KEY, EMAIL_API_SECRET), version='v3.1')
|
||||
@@ -101,3 +105,8 @@ def send_signup_email(to, subject, id, uuid, content):
|
||||
)
|
||||
|
||||
return send_email(to, subject, message, True)
|
||||
|
||||
|
||||
def admin_send_email_signupees(list, subject, content):
|
||||
for to in list:
|
||||
send_email(to, subject, markdown.markdown(content), True)
|
||||
|
||||
+41
-3
@@ -12,16 +12,17 @@ from django_filters import rest_framework as filters
|
||||
from django.db.models import Prefetch
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
from rest_framework import routers
|
||||
from rest_framework.response import Response
|
||||
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
|
||||
from rest_framework.filters import OrderingFilter, SearchFilter
|
||||
from rest_framework.decorators import action
|
||||
from rest_framework.permissions import IsAuthenticatedOrReadOnly, BasePermission, AllowAny
|
||||
from rest_framework.permissions import IsAuthenticatedOrReadOnly, BasePermission, AllowAny, IsAuthenticated
|
||||
from jsonschema import validate
|
||||
from jsonschema.exceptions import ValidationError
|
||||
|
||||
from webapp.models import *
|
||||
from webapp.serializers import *
|
||||
from webapp.utils import decode_base64_file
|
||||
from webapp.utils import admin_send_email_signupees, decode_base64_file
|
||||
|
||||
|
||||
class SignupPermission(BasePermission):
|
||||
@@ -104,9 +105,37 @@ class SignupFormViewSet(ModelViewSet):
|
||||
return SignupForm.objects.all().order_by('start_time')
|
||||
return SignupForm.objects.filter(visible=True, end_time__gt=timezone.now()).order_by('start_time')
|
||||
|
||||
@action(detail=True, methods=['post'], permission_classes=[IsAuthenticated])
|
||||
def sendemail(self, request, pk=None, *args, **kwargs):
|
||||
subject = request.data["subject"]
|
||||
content = request.data["content"]
|
||||
mode = request.data["mode"]
|
||||
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
filter = {'pk': pk}
|
||||
signupForm = get_object_or_404(queryset, **filter)
|
||||
if (mode == "all"):
|
||||
admin_send_email_signupees(signupForm.signups, subject, content)
|
||||
return JsonResponse(status=201, data={"message": "Email sent"})
|
||||
elif (mode == "actual"):
|
||||
admin_send_email_signupees(signupForm.signups[:signupForm.quota], subject, content)
|
||||
return JsonResponse(status=201, data={"message": "Email sent"})
|
||||
elif (mode == "reserved"):
|
||||
admin_send_email_signupees(signupForm.signups[signupForm.quota:], subject, content)
|
||||
return JsonResponse(status=201, data={"message": "Email sent"})
|
||||
else:
|
||||
return JsonResponse(status=400, data={"error": f"Bad mode '{mode}'"})
|
||||
|
||||
@action(detail=True, methods=['get'], permission_classes=[IsAuthenticated])
|
||||
def signups(self, request, pk=None, *args, **kwargs):
|
||||
queryset = self.filter_queryset(self.get_queryset())
|
||||
filter = {'pk': pk}
|
||||
signupForm = get_object_or_404(queryset, **filter)
|
||||
return Response(SignupSerializer(signupForm.signups, many=True).data)
|
||||
|
||||
|
||||
class SignupViewSet(ModelViewSet):
|
||||
queryset = Signup.objects.all()
|
||||
queryset = Signup.objects.filter(deleted=False)
|
||||
serializer_class = SignupSerializer
|
||||
permission_classes = [SignupPermission]
|
||||
|
||||
@@ -156,6 +185,15 @@ class SignupViewSet(ModelViewSet):
|
||||
else:
|
||||
return JsonResponse(status=404, data={"error": f"SignupForm {id} not found"})
|
||||
|
||||
def destroy(self, request, pk=None, *args, **kwargs):
|
||||
try:
|
||||
signup = self.get_object()
|
||||
signup.deleted = True
|
||||
signup.save()
|
||||
return JsonResponse(status=200, data={"message": "OK"})
|
||||
except ObjectDoesNotExist:
|
||||
return JsonResponse(status=404, data={"error": f"Signup {pk} not found"})
|
||||
|
||||
|
||||
class SavedQuestionsViewSet(ModelViewSet):
|
||||
queryset = TemplateQuestion.objects.all()
|
||||
|
||||
Reference in New Issue
Block a user