from django.conf import settings
try:
    from django.contrib.auth import get_user_model
    User = get_user_model()
    from django.contrib.auth.models import Group
except ImportError:
    from django.contrib.auth.models import User, Group

from django.core.urlresolvers import reverse
from django.http import HttpRequest
from django.test import TestCase, Client
from mock import Mock
from masquerade.middleware import MasqueradeMiddleware
import masquerade.views
import masquerade.signals

class MasqueradeTestCase(TestCase):
    """
    Tests for django-masquerade
    """

    def setUp(self):
        self.mask_on_signal_received = None
        self.mask_off_signal_received = None

        u = User.objects.create_user(username='generic',
          email='generic@foo.com', password='abc123')
        u.is_staff = False
        u.is_superuser = False
        u.save()

        u = User.objects.create_user(username='super',
          email='super@foo.com', password='abc123')
        u.is_staff = True
        u.is_superuser = True
        u.save()

        g = Group.objects.create(name='test_group')

        u = User.objects.create_user(username='staff',
          email='staff@foo.com', password='abc123')
        u.is_staff = True
        u.is_superuser = False
        u.save()
        u.groups.add(g)

        u = User.objects.create_user(username='group_member',
          email='group_member@foo.com', password='abc123')
        u.is_staff = True
        u.is_superuser = False
        u.save()
        u.groups.add(g)

    def test_mask_form_permissions(self):

        settings.MASQUERADE_REQUIRE_SUPERUSER = False
        settings.MASQUERADE_REQUIRE_COMMON_GROUP = False

        # log in as superuser
        c = Client()
        self.assertTrue(c.login(username='super', password='abc123'))

        # hit masquerade form with bad username
        response = c.post(reverse('masquerade-mask'), {'mask_user': 'nobody'})

        # verify form comes back with error
        self.assertTrue(response.status_code == 200)
        self.assertTrue(response.context['form'].is_valid() == False)

        # hit masquerade form with generic username
        response = c.post(reverse('masquerade-mask'),
          {'mask_user': 'generic'})
        self.assertTrue(response.status_code == 302)

        # make sure non-staff user cannot user form
        c = Client()
        c.login(username='generic', password='abc123')
        response = c.post(reverse('masquerade-mask'), {'mask_user': 'nobody'})
        self.assertTrue(response.status_code == 403)

        # make sure staff user can use form
        c = Client()
        c.login(username='staff', password='abc123')
        response = c.post(reverse('masquerade-mask'), {'mask_user': 'nobody'})
        self.assertTrue(response.status_code == 200)

        # ... unless require superuser setting is true.
        masquerade.views.MASQUERADE_REQUIRE_SUPERUSER = True

        c = Client()
        c.login(username='staff', password='abc123')
        response = c.post(reverse('masquerade-mask'), {'mask_user': 'nobody'})
        self.assertTrue(response.status_code == 403)

        masquerade.views.MASQUERADE_REQUIRE_SUPERUSER = False

        # hit masquerade with user of same group,
        # with REQUIRE_COMMON_GROUP as False
        c = Client()
        c.login(username='staff', password='abc123')
        response = c.post(reverse('masquerade-mask'),
          {'mask_user': 'group_member'})
        self.assertTrue(response.status_code == 302)

        # hit masquerade with user with not the same group,
        # with REQUIRE_COMMON_GROUP as False
        c = Client()
        c.login(username='staff', password='abc123')
        response = c.post(reverse('masquerade-mask'),
          {'mask_user': 'generic'})
        self.assertTrue(response.status_code == 302)

        masquerade.views.MASQUERADE_REQUIRE_COMMON_GROUP = True

        # hit masquerade with same group,
        # with REQUIRE_COMMON_GROUP as True
        c = Client()
        c.login(username='staff', password='abc123')
        response = c.post(reverse('masquerade-mask'),
          {'mask_user': 'group_member'})
        self.assertTrue(response.status_code == 302)

        # hit masquerade with user with not the same group,
        # with REQUIRE_COMMON_GROUP as True
        c = Client()
        c.login(username='staff', password='abc123')
        response = c.post(reverse('masquerade-mask'),
          {'mask_user': 'generic'})
        self.assertTrue(response.status_code == 200)
        self.assertTrue(response.context['form'].is_valid() == False)

    def test_mask_email(self):

        # log in as superuser
        c = Client()
        self.assertTrue(c.login(username='super', password='abc123'))

        # hit masquerade form with generic email
        response = c.post(reverse('masquerade-mask'),
          {'mask_user': 'generic@foo.com'})
        self.assertTrue(response.status_code == 302)

    def test_mask(self):
        mw = MasqueradeMiddleware()

        request = Mock(spec=HttpRequest)
        request.session = {'mask_user': 'generic'}
        request.user = User.objects.get_by_natural_key('super')

        mw.process_request(request)

        self.assertTrue(request.user.is_masked == True)
        self.assertTrue(request.user == User.objects.get_by_natural_key('generic'))
        self.assertTrue(request.user.original_user == User.objects.get_by_natural_key('super'))

    def test_unmask(self):
        mw = MasqueradeMiddleware()

        request = Mock(spec=HttpRequest)
        request.session = {}
        request.user = User.objects.get_by_natural_key('super')

        mw.process_request(request)

        self.assertTrue(request.user.is_masked == False)
        self.assertTrue(request.user == User.objects.get_by_natural_key('super'))
        self.assertTrue(request.user.original_user == None)

    def test_mask_on_signal_sent(self):
        def receiver(sender, mask_username, **kwargs):
            self.mask_on_signal_received = mask_username

        masquerade.signals.mask_on.connect(receiver)
        c = Client()
        c.login(username='super', password='abc123')
        c.post(reverse('masquerade-mask'),
          {'mask_user': 'generic'})
        self.assertEqual(self.mask_on_signal_received, 'generic')

    def test_mask_off_signal_sent(self):
        def receiver(sender, mask_username, **kwargs):
            self.mask_off_signal_received = mask_username

        masquerade.signals.mask_off.connect(receiver)
        c = Client()
        c.login(username='super', password='abc123')
        session = c.session
        session['mask_user'] = 'generic'
        session.save()
        c.get(reverse('masquerade-unmask'))
        self.assertEqual(self.mask_off_signal_received, 'generic')
