from django.contrib.auth import authenticate
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin

import basicauth


class DjangoBasicAuthMiddleware(MiddlewareMixin):
    """
    This middleware should be placed AFTER the standard session-based
    AuthenticationMiddleware of Django, if this one is used.

    If request.user is missing or anonymous, this middleware attempts to authenticate
    the request using basic-auth headers, which must contain valid username/password
    credentials recognized by one of the AUTHENTICATION_BACKENDS of Django.
    """

    def process_request(self, request):

        if hasattr(request, "user") and request.user.is_authenticated:
            return  # Don't interfere with standard authentication

        basic_auth_header = request.META.get("HTTP_AUTHORIZATION")
        if not basic_auth_header:
            return

        try:
            username, password = basicauth.decode(basic_auth_header)
        except basicauth.DecodeError:
            pass  # Do not log sensitive data, just let it be

        user = authenticate(request=request, username=username, password=password)

        if not user:  # Help the client guess the problem, since it attempted basic-auth
            return HttpResponse("Invalid Basic Auth credentials", status=401)

        request.user = user  # Might override an AnonymousUser