from django.contrib.auth import get_user_model

from .models import SingleUseToken

class PinBackend(object):
    """Authentication backend based on pin value."""
    def authenticate(self, request, email=None, pin=None):
        """Authenticate user based on valid pin."""
        user_model = get_user_model()
        kwargs = {
            user_model.USERNAME_FIELD: email
        }
        try:
            user = user_model.objects.get(**kwargs)
        except user_model.DoesNotExist:
            return None

        # Now that we have the user, check that we have a token
        try:
            token = self._get_token(user, pin)
        except SingleUseToken.DoesNotExist:
            return None

        if token.is_valid():
            # Read token (delete it)
            token.read()
            return user

    def _get_token(self, user, pin):
        """Get the token for corresponding user and pin."""
        return SingleUseToken.objects.get(user=user, token=pin)

from django.contrib.auth import get_user_model

from .models import SingleUseToken

class PinBackend(object):
    """Authentication backend based on pin value."""
    def authenticate(self, request, email=None, pin=None):
        """Authenticate user based on valid pin."""
        try:
            token = self._get_token(email, pin)
        except SingleUseToken.DoesNotExist:
            return None

        if token.is_valid():
            # Read token (delete it)
            token.read()
            return token.user

    def _get_token(self, email, pin):
        """Get the token for corresponding user and pin."""
        user_model = get_user_model()
        kwargs = {
            'user__%s' % user_model.USERNAME_FIELD: email,
            'token': pin
        }
        return SingleUseToken.objects.get(**kwargs)

    def get_user(self, user_id):
        """Get user from id."""
        user_model = get_user_model()
        try:
            return user_model.objects.get(pk=user_id)
        except user_model.DoesNotExist:
            return None

Refactor to query straight for user
refactor(verification): Refactor to query straight for user

- Implement get_user
- Change to make a single query to find the token, using a join to the
  user's email

  from django.contrib.auth import get_user_model
  
  from .models import SingleUseToken
  
  class PinBackend(object):
      """Authentication backend based on pin value."""
      def authenticate(self, request, email=None, pin=None):
          """Authenticate user based on valid pin."""
-         user_model = get_user_model()
-         kwargs = {
-             user_model.USERNAME_FIELD: email
-         }
          try:
-             user = user_model.objects.get(**kwargs)
-         except user_model.DoesNotExist:
-             return None
- 
-         # Now that we have the user, check that we have a token
-         try:
-             token = self._get_token(user, pin)
+             token = self._get_token(email, pin)
          except SingleUseToken.DoesNotExist:
              return None
  
          if token.is_valid():
              # Read token (delete it)
              token.read()
-             return user
+             return token.user
  
-     def _get_token(self, user, pin):
+     def _get_token(self, email, pin):
          """Get the token for corresponding user and pin."""
+         user_model = get_user_model()
+         kwargs = {
+             'user__%s' % user_model.USERNAME_FIELD: email,
+             'token': pin
+         }
-         return SingleUseToken.objects.get(user=user, token=pin)
+         return SingleUseToken.objects.get(**kwargs)
  
+     def get_user(self, user_id):
+         """Get user from id."""
+         user_model = get_user_model()
+         try:
+             return user_model.objects.get(pk=user_id)
+         except user_model.DoesNotExist:
+             return None
+ 
Refactor to query straight for user
## Code Before:
from django.contrib.auth import get_user_model

from .models import SingleUseToken

class PinBackend(object):
    """Authentication backend based on pin value."""
    def authenticate(self, request, email=None, pin=None):
        """Authenticate user based on valid pin."""
        user_model = get_user_model()
        kwargs = {
            user_model.USERNAME_FIELD: email
        }
        try:
            user = user_model.objects.get(**kwargs)
        except user_model.DoesNotExist:
            return None

        # Now that we have the user, check that we have a token
        try:
            token = self._get_token(user, pin)
        except SingleUseToken.DoesNotExist:
            return None

        if token.is_valid():
            # Read token (delete it)
            token.read()
            return user

    def _get_token(self, user, pin):
        """Get the token for corresponding user and pin."""
        return SingleUseToken.objects.get(user=user, token=pin)

## Instruction:
Refactor to query straight for user
## Code After:
from django.contrib.auth import get_user_model

from .models import SingleUseToken

class PinBackend(object):
    """Authentication backend based on pin value."""
    def authenticate(self, request, email=None, pin=None):
        """Authenticate user based on valid pin."""
        try:
            token = self._get_token(email, pin)
        except SingleUseToken.DoesNotExist:
            return None

        if token.is_valid():
            # Read token (delete it)
            token.read()
            return token.user

    def _get_token(self, email, pin):
        """Get the token for corresponding user and pin."""
        user_model = get_user_model()
        kwargs = {
            'user__%s' % user_model.USERNAME_FIELD: email,
            'token': pin
        }
        return SingleUseToken.objects.get(**kwargs)

    def get_user(self, user_id):
        """Get user from id."""
        user_model = get_user_model()
        try:
            return user_model.objects.get(pk=user_id)
        except user_model.DoesNotExist:
            return None
