from django.test import TestCase, override_settings from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType from django.core.management import call_command from django.utils.six import StringIO from perfieldperms.models import PerFieldPermission, PFPContentType from perfieldperms.utils import list_fields_for_ctype from tests import helpers @override_settings(PFP_IGNORE_PERMS={}) class PFPMakepermsTest(TestCase): def test_adds_perms(self): """ Adds appropriate number of permissions for allowed types. Takes settings from database. """ ctype = ContentType.objects.get(app_label='auth', model='user') PFPContentType.objects.create(content_type=ctype) fields = list_fields_for_ctype(ctype) num_pfps = len(fields) * 2 out = StringIO() call_command('pfp-makeperms', stdout=out) pfps = PerFieldPermission.objects.count() self.assertEqual(pfps, num_pfps) @override_settings(DEBUG=True) def test_adds_perms_output(self): """Adds PFPs with correct field values.""" ctype = ContentType.objects.get(app_label='auth', model='user') PFPContentType(content_type=ctype).save() out = StringIO() call_command('pfp-makeperms', stdout=out, verbosity=2) pfps = PerFieldPermission.objects.all() self.assertIn('Permissions added: {}'.format(len(pfps)), out.getvalue()) for pfp in pfps: with self.subTest(pfp=pfp): self.assertIn( 'Added new permission {} for field {}.{} - {}'.format( pfp.codename, pfp.content_type.app_label, pfp.content_type.model, pfp.field_name, ), out.getvalue() ) @override_settings(PFP_MODELS=[('auth', 'user')]) def test_add_perms_settings(self): """Correctly adds PFPs if configured via settings.""" ctype = ContentType.objects.get(app_label='auth', model='user') fields = list_fields_for_ctype(ctype) num_pfps = len(fields) * 2 out = StringIO() call_command('pfp-makeperms', stdout=out) pfps = PerFieldPermission.objects.count() self.assertEqual(pfps, num_pfps) @override_settings(PFP_MODELS=[('auth', 'user')]) def test_add_perms_merge(self): """Correctly merges configuration from settings and database.""" ctype = ContentType.objects.get(app_label='auth', model='group') PFPContentType.objects.create(content_type=ctype) fields = list_fields_for_ctype(ctype) ctype = ContentType.objects.get(app_label='auth', model='user') fields += list_fields_for_ctype(ctype) num_pfps = len(fields) * 2 out = StringIO() call_command('pfp-makeperms', stdout=out) pfps = PerFieldPermission.objects.count() self.assertEqual(pfps, num_pfps) @override_settings(PFP_IGNORE_DELETE=False) def test_add_perms_ignore_delete(self): """Adds delete PFPs if configured to via settings.""" ctype = ContentType.objects.get(app_label='auth', model='user') PFPContentType.objects.create(content_type=ctype) fields = list_fields_for_ctype(ctype) num_pfps = len(fields) * 3 out = StringIO() call_command('pfp-makeperms', stdout=out) pfps = PerFieldPermission.objects.count() self.assertEqual(pfps, num_pfps) @override_settings(PFP_IGNORE_PERMS={ 'auth': { 'user': ['add_user'] } }) def test_add_perms_ignore_perms(self): """Doesn't add PFPs for model permissions configured to ignore.""" ctype = ContentType.objects.get(app_label='auth', model='user') PFPContentType.objects.create(content_type=ctype) fields = list_fields_for_ctype(ctype) num_pfps = len(fields) out = StringIO() call_command('pfp-makeperms', stdout=out) pfps = PerFieldPermission.objects.count() self.assertEqual(pfps, num_pfps) @override_settings(DEBUG=True) def test_add_perms_delete_perm(self): """Deletes permissions for removed fields.""" helpers.create_pfp('auth', 'user', 'change_user', 'foo') ctype = ContentType.objects.get(app_label='auth', model='user') PFPContentType.objects.create(content_type=ctype) fields = list_fields_for_ctype(ctype) num_pfps = len(fields) * 2 out = StringIO() call_command('pfp-makeperms', stdout=out, verbosity=2) pfps = PerFieldPermission.objects.count() self.assertEqual(pfps, num_pfps) self.assertIn('Permissions deleted: 1', out.getvalue()) self.assertIn( 'Deleted permission change_user__foo for removed field auth.user - foo', out.getvalue() ) @override_settings(DEBUG=True) def test_add_perms_skip_existing(self): """Doesn't try to duplicate already existing PFPs.""" helpers.create_pfp('auth', 'user', 'change_user', 'is_staff') ctype = ContentType.objects.get(app_label='auth', model='user') PFPContentType.objects.create(content_type=ctype) fields = list_fields_for_ctype(ctype) num_created = len(fields) * 2 - 1 out = StringIO() call_command('pfp-makeperms', stdout=out, verbosity=2) self.assertIn('Permissions added: {}'.format(num_created), out.getvalue()) self.assertIn('Existing permissions skipped: 1', out.getvalue()) def test_existing_perms_removed(self): """Removed previously create permissions if configuration changed.""" ctype = ContentType.objects.get(app_label='auth', model='user') PFPContentType.objects.create(content_type=ctype) out = StringIO() call_command('pfp-makeperms', stdout=out) with self.settings(PFP_IGNORE_PERMS={'auth': {'user': ['add_user']}}): out = StringIO() call_command('pfp-makeperms', stdout=out, verbosity=2) fields = list_fields_for_ctype(ctype) num_pfps = len(fields) pfps = PerFieldPermission.objects.count() self.assertEqual(pfps, num_pfps) self.assertIn('Permissions deleted: {}'.format(len(fields)), out.getvalue()) def test_lots_of_skipping(self): """ Skip over multiple sets of PFPs to make sure loop variables are being reset properly. """ ctype = ContentType.objects.get(app_label='auth', model='user') PFPContentType.objects.create(content_type=ctype) call_command('pfp-makeperms') Permission.objects.create(content_type=ctype, codename='foo_user') fields = list_fields_for_ctype(ctype) out = StringIO() call_command('pfp-makeperms', stdout=out, verbosity=2) pfps = PerFieldPermission.objects.count() self.assertEqual(pfps, len(fields) * 3) self.assertIn('Existing permissions skipped: {}'.format(len(fields) * 2), out.getvalue()) self.assertIn('Permissions added: {}'.format(len(fields)), out.getvalue())