Browse Source

chore(): re-organize imports, fix erronous imports

Nils Wisiol 5 years ago
parent
commit
5794ff3985

+ 1 - 1
api/desecapi/emails.py

@@ -1,5 +1,5 @@
-from django.template.loader import get_template
 from django.core.mail import EmailMessage
+from django.template.loader import get_template
 
 
 def send_token_email(context, user):

+ 1 - 1
api/desecapi/exception_handlers.py

@@ -1,10 +1,10 @@
 import logging
 
 from django.db.utils import OperationalError
+from psl_dns.exceptions import UnsupportedRule
 from rest_framework import status
 from rest_framework.response import Response
 from rest_framework.views import exception_handler as drf_exception_handler
-from psl_dns.exceptions import UnsupportedRule
 
 
 def exception_handler(exc, context):

+ 1 - 1
api/desecapi/pdns.py

@@ -1,7 +1,7 @@
 import json
 import re
-import requests
 
+import requests
 from django.conf import settings
 from django.core.exceptions import SuspiciousOperation
 

+ 25 - 28
api/desecapi/serializers.py

@@ -13,10 +13,7 @@ from rest_framework.settings import api_settings
 from rest_framework.validators import UniqueTogetherValidator, UniqueValidator, qs_filter
 
 from api import settings
-# TODO organize imports
-from desecapi.models import Domain, Donation, User, RRset, Token, RR, AuthenticatedUserAction, \
-    AuthenticatedActivateUserAction, AuthenticatedChangeEmailUserAction, \
-    AuthenticatedDeleteUserAction, AuthenticatedResetPasswordUserAction, AuthenticatedAction
+from desecapi import models
 
 
 class TokenSerializer(serializers.ModelSerializer):
@@ -25,7 +22,7 @@ class TokenSerializer(serializers.ModelSerializer):
     id = serializers.ReadOnlyField(source='user_specific_id')
 
     class Meta:
-        model = Token
+        model = models.Token
         fields = ('id', 'created', 'name', 'auth_token',)
         read_only_fields = ('created', 'auth_token', 'id')
 
@@ -178,7 +175,7 @@ class RRsetSerializer(ConditionalExistenceModelSerializer):
     ttl = serializers.IntegerField(max_value=604800)
 
     class Meta:
-        model = RRset
+        model = models.RRset
         fields = ('domain', 'subname', 'name', 'records', 'ttl', 'type',)
         extra_kwargs = {
             'subname': {'required': False, 'default': NonBulkOnlyDefault('')}
@@ -211,10 +208,10 @@ class RRsetSerializer(ConditionalExistenceModelSerializer):
 
     @staticmethod
     def validate_type(value):
-        if value in RRset.DEAD_TYPES:
+        if value in models.RRset.DEAD_TYPES:
             raise serializers.ValidationError(
                 "The %s RRset type is currently unsupported." % value)
-        if value in RRset.RESTRICTED_TYPES:
+        if value in models.RRset.RESTRICTED_TYPES:
             raise serializers.ValidationError(
                 "You cannot tinker with the %s RRset." % value)
         if value.startswith('TYPE'):
@@ -231,18 +228,18 @@ class RRsetSerializer(ConditionalExistenceModelSerializer):
         return value
 
     def exists(self, arg):
-        if isinstance(arg, RRset):
+        if isinstance(arg, models.RRset):
             return arg.records.exists()
         else:
             return bool(arg.get('records')) if 'records' in arg.keys() else True
 
     def create(self, validated_data):
         rrs_data = validated_data.pop('records')
-        rrset = RRset.objects.create(**validated_data)
+        rrset = models.RRset.objects.create(**validated_data)
         self._set_all_record_contents(rrset, rrs_data)
         return rrset
 
-    def update(self, instance: RRset, validated_data):
+    def update(self, instance: models.RRset, validated_data):
         rrs_data = validated_data.pop('records', None)
         if rrs_data is not None:
             self._set_all_record_contents(instance, rrs_data)
@@ -255,7 +252,7 @@ class RRsetSerializer(ConditionalExistenceModelSerializer):
         return instance
 
     @staticmethod
-    def _set_all_record_contents(rrset: RRset, record_contents):
+    def _set_all_record_contents(rrset: models.RRset, record_contents):
         """
         Updates this RR set's resource records, discarding any old values.
 
@@ -276,8 +273,8 @@ class RRsetSerializer(ConditionalExistenceModelSerializer):
         unchanged_content = [unchanged_rr.content for unchanged_rr in unchanged_rrs]
         added_content = filter(lambda c: c not in unchanged_content, record_contents)
 
-        rrs = [RR(rrset=rrset, content=content) for content in added_content]
-        RR.objects.bulk_create(rrs)  # One INSERT
+        rrs = [models.RR(rrset=rrset, content=content) for content in added_content]
+        models.RR.objects.bulk_create(rrs)  # One INSERT
 
 
 class RRsetListSerializer(ListSerializer):
@@ -435,7 +432,7 @@ class DomainSerializer(serializers.ModelSerializer):
     psl = psl_dns.PSL(resolver=settings.PSL_RESOLVER)
 
     class Meta:
-        model = Domain
+        model = models.Domain
         fields = ('created', 'published', 'name', 'keys', 'minimum_ttl',)
         extra_kwargs = {
             'name': {'trim_whitespace': False},
@@ -474,7 +471,7 @@ class DomainSerializer(serializers.ModelSerializer):
 
         # Deny registration for non-local public suffixes and for domains covered by other users' zones
         owner = self.context['request'].user
-        queryset = Domain.objects.filter(Q(name__in=private_domains) & ~Q(owner=owner))
+        queryset = models.Domain.objects.filter(Q(name__in=private_domains) & ~Q(owner=owner))
         if is_restricted_suffix or queryset.exists():
             msg = 'This domain name is unavailable.'
             raise serializers.ValidationError(msg, code='name_unavailable')
@@ -494,7 +491,7 @@ class DomainSerializer(serializers.ModelSerializer):
 class DonationSerializer(serializers.ModelSerializer):
 
     class Meta:
-        model = Donation
+        model = models.Donation
         fields = ('name', 'iban', 'bic', 'amount', 'message', 'email')
 
     @staticmethod
@@ -509,7 +506,7 @@ class DonationSerializer(serializers.ModelSerializer):
 class UserSerializer(serializers.ModelSerializer):
 
     class Meta:
-        model = User
+        model = models.User
         fields = ('created', 'email', 'id', 'limit_domains', 'password',)
         extra_kwargs = {
             'password': {
@@ -518,7 +515,7 @@ class UserSerializer(serializers.ModelSerializer):
         }
 
     def create(self, validated_data):
-        return User.objects.create_user(**validated_data)
+        return models.User.objects.create_user(**validated_data)
 
 
 class RegisterAccountSerializer(UserSerializer):
@@ -576,7 +573,7 @@ class AuthenticatedActionSerializer(serializers.ModelSerializer):
     mac = serializers.CharField()  # serializer read-write, but model read-only field
 
     class Meta:
-        model = AuthenticatedAction
+        model = models.AuthenticatedAction
         fields = ('mac', 'created')
 
     @classmethod
@@ -590,7 +587,7 @@ class AuthenticatedActionSerializer(serializers.ModelSerializer):
         except (TypeError, UnicodeDecodeError, UnicodeEncodeError, json.JSONDecodeError, binascii.Error):
             raise ValueError
 
-    def to_representation(self, instance: AuthenticatedUserAction):
+    def to_representation(self, instance: models.AuthenticatedUserAction):
         # do the regular business
         data = super().to_representation(instance)
 
@@ -639,19 +636,19 @@ class AuthenticatedActionSerializer(serializers.ModelSerializer):
 
 class AuthenticatedUserActionSerializer(AuthenticatedActionSerializer):
     user = serializers.PrimaryKeyRelatedField(
-        queryset=User.objects.all(),
+        queryset=models.User.objects.all(),
         error_messages={'does_not_exist': 'This user does not exist.'}
     )
 
     class Meta:
-        model = AuthenticatedUserAction
+        model = models.AuthenticatedUserAction
         fields = AuthenticatedActionSerializer.Meta.fields + ('user',)
 
 
 class AuthenticatedActivateUserActionSerializer(AuthenticatedUserActionSerializer):
 
     class Meta(AuthenticatedUserActionSerializer.Meta):
-        model = AuthenticatedActivateUserAction
+        model = models.AuthenticatedActivateUserAction
         fields = AuthenticatedUserActionSerializer.Meta.fields + ('domain',)
         extra_kwargs = {
             'domain': {'default': None, 'allow_null': True}
@@ -662,7 +659,7 @@ class AuthenticatedChangeEmailUserActionSerializer(AuthenticatedUserActionSerial
     new_email = serializers.EmailField(
         validators=[
             CustomFieldNameUniqueValidator(
-                queryset=User.objects.all(),
+                queryset=models.User.objects.all(),
                 lookup_field='email',
                 message='You already have another account with this email address.',
             )
@@ -671,7 +668,7 @@ class AuthenticatedChangeEmailUserActionSerializer(AuthenticatedUserActionSerial
     )
 
     class Meta(AuthenticatedUserActionSerializer.Meta):
-        model = AuthenticatedChangeEmailUserAction
+        model = models.AuthenticatedChangeEmailUserAction
         fields = AuthenticatedUserActionSerializer.Meta.fields + ('new_email',)
 
 
@@ -679,11 +676,11 @@ class AuthenticatedResetPasswordUserActionSerializer(AuthenticatedUserActionSeri
     new_password = serializers.CharField(write_only=True)
 
     class Meta(AuthenticatedUserActionSerializer.Meta):
-        model = AuthenticatedResetPasswordUserAction
+        model = models.AuthenticatedResetPasswordUserAction
         fields = AuthenticatedUserActionSerializer.Meta.fields + ('new_password',)
 
 
 class AuthenticatedDeleteUserActionSerializer(AuthenticatedUserActionSerializer):
 
     class Meta(AuthenticatedUserActionSerializer.Meta):
-        model = AuthenticatedDeleteUserAction
+        model = models.AuthenticatedDeleteUserAction

+ 0 - 2
api/desecapi/tests/test_authentication.py

@@ -1,5 +1,3 @@
-import base64
-import json
 import re
 
 from django.core import mail

+ 0 - 2
api/desecapi/tests/test_domains.py

@@ -1,5 +1,3 @@
-import json
-
 from django.conf import settings
 from django.core import mail
 from django.core.exceptions import ValidationError

+ 0 - 7
api/desecapi/tests/test_user_management.py

@@ -12,22 +12,15 @@ This involves testing five separate endpoints:
 (4) delete user endpoint, and
 (5) verify endpoint.
 """
-import base64
-import json
 import re
-import time
-from unittest import mock
 
 from django.core import mail
-from django.test import override_settings
 from rest_framework import status
 from rest_framework.reverse import reverse
-from rest_framework.serializers import ValidationError
 from rest_framework.test import APIClient
 
 from api import settings
 from desecapi.models import Domain, User
-from desecapi.serializers import AuthenticatedUserAction
 from desecapi.tests.base import DesecTestCase, PublicSuffixMockMixin
 
 

+ 30 - 35
api/desecapi/views.py

@@ -12,9 +12,6 @@ from rest_framework import mixins
 from rest_framework import status
 from rest_framework.authentication import get_authorization_header, BaseAuthentication
 from rest_framework.exceptions import (NotFound, PermissionDenied, ValidationError)
-from rest_framework.generics import (
-    GenericAPIView, ListCreateAPIView, RetrieveUpdateDestroyAPIView, UpdateAPIView, get_object_or_404
-)
 from rest_framework.permissions import IsAuthenticated
 from rest_framework.response import Response
 from rest_framework.reverse import reverse
@@ -22,9 +19,7 @@ from rest_framework.views import APIView
 from rest_framework.viewsets import GenericViewSet
 
 import desecapi.authentication as auth
-from desecapi import serializers
-from desecapi.models import Domain, User, RRset, Token, AuthenticatedActivateUserAction, AuthenticatedChangeEmailUserAction, AuthenticatedDeleteUserAction, \
-    AuthenticatedResetPasswordUserAction
+from desecapi import serializers, models
 from desecapi.pdns_change_tracker import PDNSChangeTracker
 from desecapi.permissions import IsOwner, IsDomainOwner
 from desecapi.renderers import PlainTextRenderer
@@ -49,7 +44,7 @@ class DomainView:
         try:
             # noinspection PyAttributeOutsideInit, PyUnresolvedReferences
             self.domain = self.request.user.domains.get(name=self.kwargs['name'])
-        except Domain.DoesNotExist:
+        except models.Domain.DoesNotExist:
             raise Http404
 
 
@@ -69,15 +64,15 @@ class TokenViewSet(IdempotentDestroy,
         serializer.save(user=self.request.user)
 
 
-class DomainList(ListCreateAPIView):
+class DomainList(generics.ListCreateAPIView):
     serializer_class = serializers.DomainSerializer
     permission_classes = (IsAuthenticated, IsOwner,)
 
     def get_queryset(self):
-        return Domain.objects.filter(owner=self.request.user.pk)
+        return models.Domain.objects.filter(owner=self.request.user.pk)
 
     def perform_create(self, serializer):
-        _, parent_domain_name = Domain.partition_name(serializer.validated_data['name'])
+        _, parent_domain_name = models.Domain.partition_name(serializer.validated_data['name'])
         domain_is_local = parent_domain_name in settings.LOCAL_PUBLIC_SUFFIXES
         domain_kwargs = {'owner': self.request.user}
         if domain_is_local:
@@ -105,28 +100,28 @@ class DomainList(ListCreateAPIView):
             email.send()
 
     @staticmethod
-    def auto_delegate(domain: Domain):
+    def auto_delegate(domain: models.Domain):
         parent_domain_name = domain.partition_name()[1]
         if parent_domain_name in settings.LOCAL_PUBLIC_SUFFIXES:
-            parent_domain = Domain.objects.get(name=parent_domain_name)
+            parent_domain = models.Domain.objects.get(name=parent_domain_name)
             parent_domain.update_delegation(domain)
 
 
-class DomainDetail(IdempotentDestroy, RetrieveUpdateDestroyAPIView):
+class DomainDetail(IdempotentDestroy, generics.RetrieveUpdateDestroyAPIView):
     serializer_class = serializers.DomainSerializer
     permission_classes = (IsAuthenticated, IsOwner,)
     lookup_field = 'name'
 
-    def perform_destroy(self, instance: Domain):
+    def perform_destroy(self, instance: models.Domain):
         with PDNSChangeTracker():
             instance.delete()
         if instance.has_local_public_suffix():
-            parent_domain = Domain.objects.get(name=instance.parent_domain_name())
+            parent_domain = models.Domain.objects.get(name=instance.parent_domain_name())
             with PDNSChangeTracker():
                 parent_domain.update_delegation(instance)
 
     def get_queryset(self):
-        return Domain.objects.filter(owner=self.request.user.pk)
+        return models.Domain.objects.filter(owner=self.request.user.pk)
 
     def update(self, request, *args, **kwargs):
         try:
@@ -135,7 +130,7 @@ class DomainDetail(IdempotentDestroy, RetrieveUpdateDestroyAPIView):
             raise ValidationError(detail={"detail": e.message})
 
 
-class RRsetDetail(IdempotentDestroy, DomainView, RetrieveUpdateDestroyAPIView):
+class RRsetDetail(IdempotentDestroy, DomainView, generics.RetrieveUpdateDestroyAPIView):
     serializer_class = serializers.RRsetSerializer
     permission_classes = (IsAuthenticated, IsDomainOwner,)
 
@@ -146,7 +141,7 @@ class RRsetDetail(IdempotentDestroy, DomainView, RetrieveUpdateDestroyAPIView):
         queryset = self.filter_queryset(self.get_queryset())
 
         filter_kwargs = {k: self.kwargs[k] for k in ['subname', 'type']}
-        obj = get_object_or_404(queryset, **filter_kwargs)
+        obj = generics.get_object_or_404(queryset, **filter_kwargs)
 
         # May raise a permission denied
         self.check_object_permissions(self.request, obj)
@@ -173,19 +168,19 @@ class RRsetDetail(IdempotentDestroy, DomainView, RetrieveUpdateDestroyAPIView):
             super().perform_destroy(instance)
 
 
-class RRsetList(DomainView, ListCreateAPIView, UpdateAPIView):
+class RRsetList(DomainView, generics.ListCreateAPIView, generics.UpdateAPIView):
     serializer_class = serializers.RRsetSerializer
     permission_classes = (IsAuthenticated, IsDomainOwner,)
 
     def get_queryset(self):
-        rrsets = RRset.objects.filter(domain=self.domain)
+        rrsets = models.RRset.objects.filter(domain=self.domain)
 
         for filter_field in ('subname', 'type'):
             value = self.request.query_params.get(filter_field)
 
             if value is not None:
                 # TODO consider moving this
-                if filter_field == 'type' and value in RRset.RESTRICTED_TYPES:
+                if filter_field == 'type' and value in models.RRset.RESTRICTED_TYPES:
                     raise PermissionDenied("You cannot tinker with the %s RRset." % value)
 
                 rrsets = rrsets.filter(**{'%s__exact' % filter_field: value})
@@ -287,7 +282,7 @@ class DynDNS12Update(APIView):
 
         try:
             return self.request.user.domains.get(name=name)
-        except Domain.DoesNotExist:
+        except models.Domain.DoesNotExist:
             return None
 
     @staticmethod
@@ -417,7 +412,7 @@ class AccountCreateView(generics.CreateAPIView):
 
             domain = serializer.validated_data.get('domain')
             if domain or activation_required:
-                action = AuthenticatedActivateUserAction(user=user, domain=domain)
+                action = models.AuthenticatedActivateUserAction(user=user, domain=domain)
                 verification_code = serializers.AuthenticatedActivateUserActionSerializer(action).data['code']
                 user.send_email('activate-with-domain' if domain else 'activate', context={
                     'confirmation_link': reverse('confirm-activate-account', request=request, args=[verification_code])
@@ -436,12 +431,12 @@ class AccountView(generics.RetrieveAPIView):
         return self.request.user
 
 
-class AccountDeleteView(GenericAPIView):
+class AccountDeleteView(generics.GenericAPIView):
     authentication_classes = (auth.EmailPasswordPayloadAuthentication,)
     permission_classes = (IsAuthenticated,)
 
     def post(self, request, *args, **kwargs):
-        action = AuthenticatedDeleteUserAction(user=self.request.user)
+        action = models.AuthenticatedDeleteUserAction(user=self.request.user)
         verification_code = serializers.AuthenticatedDeleteUserActionSerializer(action).data['code']
         request.user.send_email('delete-user', context={
             'confirmation_link': reverse('confirm-delete-account', request=request, args=[verification_code])
@@ -451,21 +446,21 @@ class AccountDeleteView(GenericAPIView):
                         status=status.HTTP_202_ACCEPTED)
 
 
-class AccountLoginView(GenericAPIView):
+class AccountLoginView(generics.GenericAPIView):
     authentication_classes = (auth.EmailPasswordPayloadAuthentication,)
     permission_classes = (IsAuthenticated,)
 
     def post(self, request, *args, **kwargs):
         user = self.request.user
 
-        token = Token.objects.create(user=user, name="login")
+        token = models.Token.objects.create(user=user, name="login")
         user_logged_in.send(sender=user.__class__, request=self.request, user=user)
 
         data = serializers.TokenSerializer(token).data
         return Response(data)
 
 
-class AccountChangeEmailView(GenericAPIView):
+class AccountChangeEmailView(generics.GenericAPIView):
     authentication_classes = (auth.EmailPasswordPayloadAuthentication,)
     permission_classes = (IsAuthenticated,)
     serializer_class = serializers.ChangeEmailSerializer
@@ -476,7 +471,7 @@ class AccountChangeEmailView(GenericAPIView):
         serializer.is_valid(raise_exception=True)
         new_email = serializer.validated_data['new_email']
 
-        action = AuthenticatedChangeEmailUserAction(user=request.user, new_email=new_email)
+        action = models.AuthenticatedChangeEmailUserAction(user=request.user, new_email=new_email)
         verification_code = serializers.AuthenticatedChangeEmailUserActionSerializer(action).data['code']
         request.user.send_email('change-email', recipient=new_email, context={
             'confirmation_link': reverse('confirm-change-email', request=request, args=[verification_code]),
@@ -489,7 +484,7 @@ class AccountChangeEmailView(GenericAPIView):
                         status=status.HTTP_202_ACCEPTED)
 
 
-class AccountResetPasswordView(GenericAPIView):
+class AccountResetPasswordView(generics.GenericAPIView):
     serializer_class = serializers.EmailSerializer
 
     def post(self, request, *args, **kwargs):
@@ -497,11 +492,11 @@ class AccountResetPasswordView(GenericAPIView):
         serializer.is_valid(raise_exception=True)
         try:
             email = serializer.validated_data['email']
-            user = User.objects.get(email=email, is_active=True)
-        except User.DoesNotExist:
+            user = models.User.objects.get(email=email, is_active=True)
+        except models.User.DoesNotExist:
             pass
         else:
-            action = AuthenticatedResetPasswordUserAction(user=user)
+            action = models.AuthenticatedResetPasswordUserAction(user=user)
             verification_code = serializers.AuthenticatedResetPasswordUserActionSerializer(action).data['code']
             user.send_email('reset-password', context={
                 'confirmation_link': reverse('confirm-reset-password', request=request, args=[verification_code])
@@ -513,7 +508,7 @@ class AccountResetPasswordView(GenericAPIView):
                         status=status.HTTP_202_ACCEPTED)
 
 
-class AuthenticatedActionView(GenericAPIView):
+class AuthenticatedActionView(generics.GenericAPIView):
     """
     Abstract class. Deserializes the given payload according the serializers specified by the view extending
     this class. If the `serializer.is_valid`, `act` is called on the action object.
@@ -597,7 +592,7 @@ class AuthenticatedActivateUserActionView(AuthenticatedActionView):
 
         if domain.parent_domain_name() in settings.LOCAL_PUBLIC_SUFFIXES:
             PDNSChangeTracker.track(lambda: DomainList.auto_delegate(domain))
-            token = Token.objects.create(user=action.user, name='dyndns')
+            token = models.Token.objects.create(user=action.user, name='dyndns')
             return Response({
                 'detail': 'Success! Here is the password ("auth_token") to configure your router (or any other dynDNS '
                           'client). This password is different from your account password for security reasons.',