from ldt.security import set_current_user

from django.contrib.auth import login
from tastypie.authentication import (
    SessionAuthentication as TastypieSessionAuthentication,
    ApiKeyAuthentication as TastypieApiKeyAuthentication)
from tastypie.http import HttpUnauthorized


class SessionAuthentication(TastypieSessionAuthentication):
    """
    An authentication mechanism that piggy-backs on Django sessions.
    
    This is useful when the API is talking to Javascript on the same site.
    Relies on the user being logged in through the standard Django login
    setup.
    
    Requires a valid CSRF token.
    """
    def is_authenticated(self, request, **kwargs):
        """
        Checks to make sure the user is logged in & has a Django session.
        """
        # Cargo-culted from Django 1.3/1.4's ``django/middleware/csrf.py``.
        # We can't just use what's there, since the return values will be
        # wrong.
        # We also can't risk accessing ``request.POST``, which will break with
        # the serialized bodies.
        if request.method in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
            return True
        return super(SessionAuthentication, self).is_authenticated(request, **kwargs)

    def get_identifier(self, request):
        """
        Provides a unique string identifier for the requestor.
        
        This implementation returns the user's username.
        """
        return request.user.username or "anon."


class ApiKeyAuthentication(TastypieApiKeyAuthentication):
    """
    Handles API key auth, in which a user provides a username & API key.

    Uses the ``ApiKey`` model that ships with tastypie. If you wish to use
    a different model, override the ``get_key`` method to perform the key check
    as suits your needs.
    """

    def is_authenticated(self, request, **kwargs):
        """
        Finds the user and checks their API key.

        Should return either ``True`` if allowed, ``False`` if not or an
        ``HttpResponse`` if you need something custom.
        """
        resp = super(ApiKeyAuthentication, self).is_authenticated(request, **kwargs)

        if resp and not isinstance(resp, HttpUnauthorized) and request.user:
            request.user.backend = "django.contrib.auth.backends.ModelBackend"
            login(request, request.user)
            set_current_user(request.user)

        return resp


    def get_identifier(self, request):
        """
        Provides a unique string identifier for the requestor.

        This implementation returns the user's username.
        """
        username, _ = self.extract_credentials(request)
        return username or 'anon.'
