from django.contrib.auth.models import User, Group
from django.contrib.contenttypes.models import ContentType
from django.core.management import call_command
from django.test import TestCase

from guardian.utils import clean_orphan_obj_perms
from guardian.shortcuts import assign


class OrphanedObjectPermissionsTest(TestCase):

    def setUp(self):
        # Create objects for which we would assing obj perms
        self.target_user1 = User.objects.create(username='user1')
        self.target_group1 = Group.objects.create(name='group1')
        self.target_obj1 = ContentType.objects.create(name='ct1', model='foo',
            app_label='fake-for-guardian-tests')
        self.target_obj2 = ContentType.objects.create(name='ct2', model='bar',
            app_label='fake-for-guardian-tests')


        self.user = User.objects.create(username='user')
        self.group = Group.objects.create(name='group')

    def test_clean_perms(self):

        # assign obj perms
        target_perms = {
            self.target_user1: ["change_user"],
            self.target_group1: ["delete_group"],
            self.target_obj1: ["change_contenttype", "delete_contenttype"],
            self.target_obj2: ["change_contenttype"],
        }
        obj_perms_count = sum([len(val) for key, val in target_perms.items()])
        for target, perms in target_perms.items():
            target.__old_pk = target.pk # Store pkeys
            for perm in perms:
                assign(perm, self.user, target)

        # Remove targets
        for target, perms in target_perms.items():
            target.delete()

        # Clean orphans
        removed = clean_orphan_obj_perms()
        self.assertEqual(removed, obj_perms_count)

        # Recreate targets and check if user has no permissions
        for target, perms in target_perms.items():
            target.pk = target.__old_pk
            target.save()
            for perm in perms:
                self.assertFalse(self.user.has_perm(perm, target))

    def test_clean_perms_command(self):
        """
        Same test as the one above but rather function directly, we call
        management command instead.
        """

        # assign obj perms
        target_perms = {
            self.target_user1: ["change_user"],
            self.target_group1: ["delete_group"],
            self.target_obj1: ["change_contenttype", "delete_contenttype"],
            self.target_obj2: ["change_contenttype"],
        }
        for target, perms in target_perms.items():
            target.__old_pk = target.pk # Store pkeys
            for perm in perms:
                assign(perm, self.user, target)

        # Remove targets
        for target, perms in target_perms.items():
            target.delete()

        # Clean orphans
        call_command("clean_orphan_obj_perms", verbosity=0)

        # Recreate targets and check if user has no permissions
        for target, perms in target_perms.items():
            target.pk = target.__old_pk
            target.save()
            for perm in perms:
                self.assertFalse(self.user.has_perm(perm, target))

