From 09ef3c50718b8cb86c87f59b7d7948f4f3396a2f Mon Sep 17 00:00:00 2001 From: jsangmeister Date: Tue, 5 Nov 2019 09:30:55 +0100 Subject: [PATCH] add settings variable ENABLE_ELECTRONIC_VOTING --- openslides/poll/serializers.py | 26 ++++++++++++- openslides/utils/settings.py.tpl | 4 ++ tests/integration/assignments/test_polls.py | 29 ++++++++++++++ tests/integration/motions/test_polls.py | 43 ++++++++++++++++++--- tests/settings.py | 2 + 5 files changed, 97 insertions(+), 7 deletions(-) diff --git a/openslides/poll/serializers.py b/openslides/poll/serializers.py index 74af68396..fa30e8453 100644 --- a/openslides/poll/serializers.py +++ b/openslides/poll/serializers.py @@ -1,3 +1,5 @@ +from django.conf import settings + from ..utils.auth import get_group_model from ..utils.rest_api import ( CharField, @@ -5,7 +7,9 @@ from ..utils.rest_api import ( IdPrimaryKeyRelatedField, ModelSerializer, SerializerMethodField, + ValidationError, ) +from .models import BasePoll BASE_VOTE_FIELDS = ("id", "weight", "value", "user", "option", "pollstate") @@ -77,10 +81,10 @@ class BasePollSerializer(ModelSerializer): def update(self, instance, validated_data): """ Adjusts the 100%-base to the pollmethod. This might be needed, - if at least one of them was changed. Wrong comobinations should be + if at least one of them was changed. Wrong combinations should be also handled by the client, but here we make it sure aswell! - E.g. the pollmethod is YN, but the 100%-base is YNA, this micht noght be + E.g. the pollmethod is YN, but the 100%-base is YNA, this might not be possible (see implementing serializers to see forbidden combinations) """ old_100_percent_base = instance.onehundred_percent_base @@ -95,6 +99,24 @@ class BasePollSerializer(ModelSerializer): return instance + def validate(self, data): + """ + Check that the given polltype is allowed. + """ + # has to be called in function instead of globally to enable tests to change the setting + ENABLE_ELECTRONIC_VOTING = getattr(settings, "ENABLE_ELECTRONIC_VOTING", False) + if ( + "type" in data + and data["type"] != BasePoll.TYPE_ANALOG + and not ENABLE_ELECTRONIC_VOTING + ): + raise ValidationError( + { + "detail": "Electronic voting is disabled. Only analog polls are allowed" + } + ) + return data + def norm_100_percent_base_to_pollmethod( self, onehundred_percent_base, pollmethod, old_100_percent_base=None ): diff --git a/openslides/utils/settings.py.tpl b/openslides/utils/settings.py.tpl index 949bb244b..4d23ce567 100644 --- a/openslides/utils/settings.py.tpl +++ b/openslides/utils/settings.py.tpl @@ -127,6 +127,10 @@ if ENABLE_SAML: INSTALLED_APPS += ['openslides.saml'] +# Controls if electronic voting (means non-analog polls) are enabled. +ENABLE_ELECTRONIC_VOTING = False + + # Internationalization # https://docs.djangoproject.com/en/1.10/topics/i18n/ diff --git a/tests/integration/assignments/test_polls.py b/tests/integration/assignments/test_polls.py index f7a963acb..05473ddf3 100644 --- a/tests/integration/assignments/test_polls.py +++ b/tests/integration/assignments/test_polls.py @@ -3,6 +3,7 @@ from decimal import Decimal from typing import Any import pytest +from django.conf import settings from django.contrib.auth import get_user_model from django.urls import reverse from rest_framework import status @@ -242,6 +243,23 @@ class CreateAssignmentPoll(TestCase): self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertFalse(AssignmentPoll.objects.exists()) + def test_not_allowed_type(self): + setattr(settings, "ENABLE_ELECTRONIC_VOTING", False) + response = self.client.post( + reverse("assignmentpoll-list"), + { + "title": "test_title_yaiyeighoh0Iraet3Ahc", + "pollmethod": AssignmentPoll.POLLMETHOD_YNA, + "type": AssignmentPoll.TYPE_NAMED, + "assignment_id": self.assignment.id, + "onehundred_percent_base": AssignmentPoll.PERCENT_BASE_YN, + "majority_method": AssignmentPoll.MAJORITY_SIMPLE, + }, + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertFalse(AssignmentPoll.objects.exists()) + setattr(settings, "ENABLE_ELECTRONIC_VOTING", True) + def test_not_supported_pollmethod(self): response = self.client.post( reverse("assignmentpoll-list"), @@ -415,6 +433,17 @@ class UpdateAssignmentPoll(TestCase): poll = AssignmentPoll.objects.get() self.assertEqual(poll.type, "named") + def test_patch_not_allowed_type(self): + setattr(settings, "ENABLE_ELECTRONIC_VOTING", False) + response = self.client.patch( + reverse("assignmentpoll-detail", args=[self.poll.pk]), + {"type": BasePoll.TYPE_NAMED}, + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + poll = AssignmentPoll.objects.get() + self.assertEqual(poll.type, BasePoll.TYPE_NAMED) + setattr(settings, "ENABLE_ELECTRONIC_VOTING", False) + def test_patch_groups_to_empty(self): response = self.client.patch( reverse("assignmentpoll-detail", args=[self.poll.pk]), {"groups_id": []}, diff --git a/tests/integration/motions/test_polls.py b/tests/integration/motions/test_polls.py index 284d5d88d..bae17cf8e 100644 --- a/tests/integration/motions/test_polls.py +++ b/tests/integration/motions/test_polls.py @@ -1,6 +1,7 @@ from decimal import Decimal import pytest +from django.conf import settings from django.contrib.auth import get_user_model from django.urls import reverse from rest_framework import status @@ -151,11 +152,11 @@ class CreateMotionPoll(TestCase): reverse("motionpoll-list"), { "title": "test_title_Thoo2eiphohhi1eeXoow", - "pollmethod": "YNA", - "type": "named", + "pollmethod": MotionPoll.POLLMETHOD_YNA, + "type": MotionPoll.TYPE_NAMED, "motion_id": self.motion.id, - "onehundred_percent_base": "YN", - "majority_method": "simple", + "onehundred_percent_base": MotionPoll.PERCENT_BASE_YN, + "majority_method": MotionPoll.MAJORITY_SIMPLE, "groups_id": [], }, ) @@ -168,14 +169,33 @@ class CreateMotionPoll(TestCase): reverse("motionpoll-list"), { "title": "test_title_yaiyeighoh0Iraet3Ahc", - "pollmethod": "YNA", + "pollmethod": MotionPoll.POLLMETHOD_YNA, "type": "not_existing", "motion_id": self.motion.id, + "onehundred_percent_base": MotionPoll.PERCENT_BASE_YN, + "majority_method": MotionPoll.MAJORITY_SIMPLE, }, ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) self.assertFalse(MotionPoll.objects.exists()) + def test_not_allowed_type(self): + setattr(settings, "ENABLE_ELECTRONIC_VOTING", False) + response = self.client.post( + reverse("motionpoll-list"), + { + "title": "test_title_3jdWIXbKBa7ZXutf3RYf", + "pollmethod": MotionPoll.POLLMETHOD_YN, + "type": MotionPoll.TYPE_NAMED, + "motion_id": self.motion.id, + "onehundred_percent_base": MotionPoll.PERCENT_BASE_YN, + "majority_method": MotionPoll.MAJORITY_SIMPLE, + }, + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + self.assertFalse(MotionPoll.objects.exists()) + setattr(settings, "ENABLE_ELECTRONIC_VOTING", True) + def test_not_supported_pollmethod(self): response = self.client.post( reverse("motionpoll-list"), @@ -184,6 +204,8 @@ class CreateMotionPoll(TestCase): "pollmethod": "not_existing", "type": "named", "motion_id": self.motion.id, + "onehundred_percent_base": MotionPoll.PERCENT_BASE_YN, + "majority_method": MotionPoll.MAJORITY_SIMPLE, }, ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) @@ -270,6 +292,17 @@ class UpdateMotionPoll(TestCase): poll = MotionPoll.objects.get() self.assertEqual(poll.type, "named") + def test_patch_not_allowed_type(self): + setattr(settings, "ENABLE_ELECTRONIC_VOTING", False) + response = self.client.patch( + reverse("motionpoll-detail", args=[self.poll.pk]), + {"type": BasePoll.TYPE_NAMED}, + ) + self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + poll = MotionPoll.objects.get() + self.assertEqual(poll.type, BasePoll.TYPE_NAMED) + setattr(settings, "ENABLE_ELECTRONIC_VOTING", True) + def test_patch_100_percent_base(self): response = self.client.patch( reverse("motionpoll-detail", args=[self.poll.pk]), diff --git a/tests/settings.py b/tests/settings.py index 734f1ca6f..1366534df 100644 --- a/tests/settings.py +++ b/tests/settings.py @@ -75,3 +75,5 @@ PASSWORD_HASHERS = ["django.contrib.auth.hashers.MD5PasswordHasher"] RESTRICTED_DATA_CACHE = False REST_FRAMEWORK = {"TEST_REQUEST_DEFAULT_FORMAT": "json"} + +ENABLE_ELECTRONIC_VOTING = True