From f5045402387e3c415d21c901a188bad83b51f776 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20Loipf=C3=BChrer?= <michael.loipfuehrer@stusta.de>
Date: Sun, 13 Jun 2021 18:39:25 +0200
Subject: [PATCH] fix development setup with corsheaders and pylint

---
 .pylintrc                      |  1 +
 requirements_dev.txt           |  1 +
 rest_api/channelsmiddleware.py |  4 ++--
 rest_api/serializers.py        | 13 ++++++-------
 rest_api/views.py              |  2 ++
 vote/models.py                 |  6 ++++--
 wahlfang/settings.py           | 13 ++++++++-----
 7 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/.pylintrc b/.pylintrc
index 202755e..d2e87aa 100644
--- a/.pylintrc
+++ b/.pylintrc
@@ -48,3 +48,4 @@ disable=print-statement,
         no-member,
         unused-import,
         fixme, # no TODOs
+        too-many-ancestors,
diff --git a/requirements_dev.txt b/requirements_dev.txt
index a93b314..59987ff 100644
--- a/requirements_dev.txt
+++ b/requirements_dev.txt
@@ -1,4 +1,5 @@
 bandit==1.6.2
 pylint==2.7.*
 pylint-django~=2.3.0
+django-cors-headers~=3.7.0
 django-stubs
diff --git a/rest_api/channelsmiddleware.py b/rest_api/channelsmiddleware.py
index acc5559..782b33c 100644
--- a/rest_api/channelsmiddleware.py
+++ b/rest_api/channelsmiddleware.py
@@ -1,7 +1,7 @@
 from urllib.parse import parse_qs
 
-from django.conf import settings
 from channels.db import database_sync_to_async
+from django.conf import settings
 from django.db import close_old_connections
 from jwt import decode as jwt_decode
 from rest_framework_simplejwt.exceptions import InvalidToken, TokenError
@@ -35,7 +35,7 @@ class WebsocketJWTAuthMiddleware:
         try:
             # This will automatically validate the token and raise an error if token is invalid
             UntypedToken(token)
-        except (InvalidToken, TokenError) as e:
+        except (InvalidToken, TokenError):
             # Token is invalid
             return None
         else:
diff --git a/rest_api/serializers.py b/rest_api/serializers.py
index 42bc44d..8a0f020 100644
--- a/rest_api/serializers.py
+++ b/rest_api/serializers.py
@@ -4,11 +4,10 @@ from rest_framework import serializers
 from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
 from rest_framework_simplejwt.tokens import RefreshToken
 
-from vote.models import Election, Session, Application, Voter, VOTE_CHOICES, VOTE_CHOICES_NO_ABSTENTION, OpenVote, \
-    VOTE_ACCEPT, Vote
+from vote.models import Election, Session, Application, Voter
 
 
-class TokenObtainVoterSerializer(serializers.Serializer):
+class TokenObtainVoterSerializer(serializers.Serializer):  # pylint: disable=W0223
 
     def __init__(self, *args, **kwargs):
         super().__init__(*args, **kwargs)
@@ -24,11 +23,11 @@ class TokenObtainVoterSerializer(serializers.Serializer):
         except KeyError:
             pass
 
-        self.user = authenticate(**authenticate_kwargs)
-        if not self.user:
+        user = authenticate(**authenticate_kwargs)
+        if not user:
             raise serializers.ValidationError('could not authenticate user')
 
-        refresh = self.get_token(self.user)
+        refresh = self.get_token(user)
         data = {
             'refresh': str(refresh),
             'access': str(refresh.access_token),
@@ -42,7 +41,7 @@ class TokenObtainVoterSerializer(serializers.Serializer):
         return token
 
 
-class TokenObtainElectionManagerSerializer(TokenObtainPairSerializer):
+class TokenObtainElectionManagerSerializer(TokenObtainPairSerializer):  # pylint: disable=W0223
     @classmethod
     def get_token(cls, user):
         token = super().get_token(user)
diff --git a/rest_api/views.py b/rest_api/views.py
index a434c8d..7f516ed 100644
--- a/rest_api/views.py
+++ b/rest_api/views.py
@@ -89,3 +89,5 @@ class ElectionViewset(viewsets.ReadOnlyModelViewSet):
                 return Response(data={'error': 'not found'}, status=status.HTTP_404_NOT_FOUND)
             application.delete()
             return Response(status=status.HTTP_204_NO_CONTENT)
+
+        return Response(status=status.HTTP_400_BAD_REQUEST)
diff --git a/vote/models.py b/vote/models.py
index ad5a8fb..22c5811 100644
--- a/vote/models.py
+++ b/vote/models.py
@@ -271,7 +271,8 @@ class Voter(models.Model):
             email = email_name + '@' + domain_part.lower()
         return email
 
-    def email_user(self, subject, message, from_email=None, **kwargs) -> Tuple[Optional['Voter'], Optional[str]]:
+    def email_user(self, subject, message, from_email=None, **kwargs) -> Tuple[
+        Optional['Voter'], Optional[str]]:  # pylint: disable=E1136
         """Send an email to this user."""
         if self.email is not None:
             try:
@@ -329,7 +330,8 @@ class Voter(models.Model):
 
         Voter.send_invitation(test_voter, "mock-up-access-token", from_email)
 
-    def send_invitation(self, access_code: str, from_email: str) -> Tuple[Optional['Voter'], Optional[str]]:
+    def send_invitation(self, access_code: str, from_email: str) -> Tuple[
+        Optional['Voter'], Optional[str]]:  # pylint: disable=E1136
         if not self.email:
             return None, None
         subject = f'Invitation for {self.session.title}'
diff --git a/wahlfang/settings.py b/wahlfang/settings.py
index caafcd9..f3ceb3a 100644
--- a/wahlfang/settings.py
+++ b/wahlfang/settings.py
@@ -12,11 +12,9 @@ https://docs.djangoproject.com/en/3.0/ref/settings/
 
 import logging
 import os
-
 # Build paths inside the project like this: os.path.join(BASE_DIR, ...)
 from datetime import timedelta
 
-from corsheaders.defaults import default_headers
 from django.urls import reverse_lazy
 
 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -52,7 +50,6 @@ INSTALLED_APPS = [
     'django.contrib.sessions',
     'django.contrib.messages',
     'django.contrib.staticfiles',
-    'corsheaders',
     'rest_framework',
     'crispy_forms',
     'vote',
@@ -61,11 +58,13 @@ INSTALLED_APPS = [
     'channels',
 ]
 
+if DEBUG:
+    INSTALLED_APPS += ['corsheaders']
+
 if EXPORT_PROMETHEUS_METRICS:
     INSTALLED_APPS += ['django_prometheus']
 
 MIDDLEWARE = [
-    'corsheaders.middleware.CorsMiddleware',
     'django.middleware.security.SecurityMiddleware',
     'django.contrib.sessions.middleware.SessionMiddleware',
     'django.middleware.common.CommonMiddleware',
@@ -76,12 +75,16 @@ MIDDLEWARE = [
     'csp.middleware.CSPMiddleware',
 ]
 
+if DEBUG:
+    MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware'] + MIDDLEWARE
+
 if EXPORT_PROMETHEUS_METRICS:
     MIDDLEWARE = ['django_prometheus.middleware.PrometheusBeforeMiddleware'] + \
                  MIDDLEWARE + \
                  ['django_prometheus.middleware.PrometheusAfterMiddleware']
 
-CORS_ALLOW_ALL_ORIGINS = True
+if DEBUG:
+    CORS_ALLOW_ALL_ORIGINS = True
 
 ROOT_URLCONF = 'wahlfang.urls'
 
-- 
GitLab