from django.contrib.auth.models import User, Group, check_password
from django.contrib.auth import backends
from django.contrib import auth
from django import http

from autotest_lib.client.cros import constants
from autotest_lib.frontend import thread_local
from autotest_lib.frontend.afe import models, management
from autotest_lib.server import utils

DEBUG_USER = 'debug_user'

class SimpleAuthBackend(backends.ModelBackend):
    """
    Automatically allows any login.  This backend is for use when Apache is
    doing the real authentication.  Also ensures logged-in user exists in
    frontend.afe.models.User database.
    """
    def authenticate(self, username=None, password=None):
        try:
            user = User.objects.get(username=username)
        except User.DoesNotExist:
            # password is meaningless
            user = User(username=username,
                        password='apache authentication')
            user.is_staff = True
            user.save() # need to save before adding groups
            user.groups.add(Group.objects.get(
                name=management.BASIC_ADMIN))

        SimpleAuthBackend.check_afe_user(username)
        return user


    @staticmethod
    def check_afe_user(username):
        user, created = models.User.objects.get_or_create(login=username)
        if created:
            user.save()

    def get_user(self, user_id):
        try:
            return User.objects.get(pk=user_id)
        except User.DoesNotExist:
            return None


class GetApacheUserMiddleware(object):
    """
    Middleware for use when Apache is doing authentication.  Looks for
    REMOTE_USER in headers and passed the username found to
    thread_local.set_user().  If no such header is found, looks for
    HTTP_AUTHORIZATION header with username (this allows CLI to authenticate).
    If neither of those are found, DEBUG_USER is used.
    """

    def process_request(self, request):
        # look for a username from Apache
        user = request.META.get('REMOTE_USER')
        if user is None:
            # look for a user in headers.  This is insecure but
            # it's our temporarily solution for CLI auth.
            user = request.META.get('HTTP_AUTHORIZATION')
        if user is None:
            # no user info - assume we're in development mode
            user = constants.MOBLAB_USER if utils.is_moblab() else DEBUG_USER
        thread_local.set_user(user)


class ApacheAuthMiddleware(GetApacheUserMiddleware):
    """
    Like GetApacheUserMiddleware, but also logs the user into Django's auth
    system, and replaces the username in thread_local with the actual User model
    object.
    """


    def process_request(self, request):
        super(ApacheAuthMiddleware, self).process_request(request)
        username = thread_local.get_user()
        thread_local.set_user(None)
        user_object = auth.authenticate(username=username,
                                        password='')
        auth.login(request, user_object)
        thread_local.set_user(models.User.objects.get(login=username))
