188 lines
7.2 KiB
Python
188 lines
7.2 KiB
Python
"""
|
|
Unit tests for user_management management commands.
|
|
"""
|
|
|
|
|
|
import sys
|
|
import pytest
|
|
import ddt
|
|
|
|
from django.contrib.auth.models import Group, Permission
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.core.management import CommandError, call_command
|
|
from django.test import TestCase
|
|
|
|
TEST_EMAIL = 'test@example.com'
|
|
TEST_GROUP = 'test-group'
|
|
TEST_USERNAME = 'test-user'
|
|
TEST_DATA = (
|
|
{},
|
|
{
|
|
TEST_GROUP: ['add_group', 'change_group', 'change_group'],
|
|
},
|
|
{
|
|
'other-group': ['add_group', 'change_group', 'change_group'],
|
|
},
|
|
)
|
|
|
|
|
|
@ddt.ddt
|
|
class TestManageGroupCommand(TestCase):
|
|
"""
|
|
Tests the `manage_group` command.
|
|
"""
|
|
|
|
def set_group_permissions(self, group_permissions):
|
|
"""
|
|
Sets up a before-state for groups and permissions in tests, which
|
|
can be checked afterward to ensure that a failed atomic
|
|
operation has not had any side effects.
|
|
"""
|
|
content_type = ContentType.objects.get_for_model(Group)
|
|
for group_name, permission_codenames in group_permissions.items():
|
|
group = Group.objects.create(name=group_name)
|
|
for codename in permission_codenames:
|
|
group.permissions.add(
|
|
Permission.objects.get(content_type=content_type, codename=codename)
|
|
)
|
|
|
|
def check_group_permissions(self, group_permissions):
|
|
"""
|
|
Checks that the current state of the database matches the specified groups and
|
|
permissions.
|
|
"""
|
|
self.check_groups(list(group_permissions.keys()))
|
|
for group_name, permission_codenames in group_permissions.items():
|
|
self.check_permissions(group_name, permission_codenames)
|
|
|
|
def check_groups(self, group_names):
|
|
"""
|
|
DRY helper.
|
|
"""
|
|
assert set(group_names) == {g.name for g in Group.objects.all()}
|
|
|
|
def check_permissions(self, group_name, permission_codenames):
|
|
"""
|
|
DRY helper.
|
|
"""
|
|
assert set(permission_codenames) == {p.codename for p in Group.objects.get(name=group_name).permissions.all()}
|
|
|
|
@ddt.data(
|
|
*(
|
|
(data, args, exception)
|
|
for data in TEST_DATA
|
|
for args, exception in (
|
|
((), 'too few arguments' if sys.version_info.major == 2 else 'required: group_name'), # no group name
|
|
(('x' * 151,), 'invalid group name'), # invalid group name
|
|
((TEST_GROUP, 'some-other-group'), 'unrecognized arguments'), # multiple arguments
|
|
((TEST_GROUP, '--some-option', 'dummy'), 'unrecognized arguments') # unexpected option name
|
|
)
|
|
)
|
|
)
|
|
@ddt.unpack
|
|
def test_invalid_input(self, initial_group_permissions, command_args, exception_message):
|
|
"""
|
|
Ensures that invalid inputs result in errors with relevant output,
|
|
and that no persistent state is changed.
|
|
"""
|
|
self.set_group_permissions(initial_group_permissions)
|
|
|
|
with pytest.raises(CommandError) as exc_context:
|
|
call_command('manage_group', *command_args)
|
|
assert exception_message in str(exc_context.value).lower()
|
|
self.check_group_permissions(initial_group_permissions)
|
|
|
|
@ddt.data(*TEST_DATA)
|
|
def test_invalid_permission(self, initial_group_permissions):
|
|
"""
|
|
Ensures that a permission that cannot be parsed or resolved results in
|
|
and error and that no persistent state is changed.
|
|
"""
|
|
self.set_group_permissions(initial_group_permissions)
|
|
|
|
# not parseable
|
|
with pytest.raises(CommandError) as exc_context:
|
|
call_command('manage_group', TEST_GROUP, '--permissions', 'fail')
|
|
assert 'invalid permission option' in str(exc_context.value).lower()
|
|
self.check_group_permissions(initial_group_permissions)
|
|
|
|
# not parseable
|
|
with pytest.raises(CommandError) as exc_context:
|
|
call_command('manage_group', TEST_GROUP, '--permissions', 'f:a:i:l')
|
|
assert 'invalid permission option' in str(exc_context.value).lower()
|
|
self.check_group_permissions(initial_group_permissions)
|
|
|
|
# invalid app label
|
|
with pytest.raises(CommandError) as exc_context:
|
|
call_command('manage_group', TEST_GROUP, '--permissions', 'nonexistent-label:dummy-model:dummy-perm')
|
|
assert 'no installed app' in str(exc_context.value).lower()
|
|
assert 'nonexistent-label' in str(exc_context.value).lower()
|
|
self.check_group_permissions(initial_group_permissions)
|
|
|
|
# invalid model name
|
|
with pytest.raises(CommandError) as exc_context:
|
|
call_command('manage_group', TEST_GROUP, '--permissions', 'auth:nonexistent-model:dummy-perm')
|
|
assert 'nonexistent-model' in str(exc_context.value).lower()
|
|
self.check_group_permissions(initial_group_permissions)
|
|
|
|
# invalid model name
|
|
with pytest.raises(CommandError) as exc_context:
|
|
call_command('manage_group', TEST_GROUP, '--permissions', 'auth:Group:nonexistent-perm')
|
|
assert 'invalid permission codename' in str(exc_context.value).lower()
|
|
assert 'nonexistent-perm' in str(exc_context.value).lower()
|
|
self.check_group_permissions(initial_group_permissions)
|
|
|
|
def test_group(self):
|
|
"""
|
|
Ensures that groups are created if they don't exist and reused if they do.
|
|
"""
|
|
self.check_groups([])
|
|
call_command('manage_group', TEST_GROUP)
|
|
self.check_groups([TEST_GROUP])
|
|
|
|
# check idempotency
|
|
call_command('manage_group', TEST_GROUP)
|
|
self.check_groups([TEST_GROUP])
|
|
|
|
def test_group_remove(self):
|
|
"""
|
|
Ensures that groups are removed if they exist and we exit cleanly otherwise.
|
|
"""
|
|
self.set_group_permissions({TEST_GROUP: ['add_group']})
|
|
self.check_groups([TEST_GROUP])
|
|
call_command('manage_group', TEST_GROUP, '--remove')
|
|
self.check_groups([])
|
|
|
|
# check idempotency
|
|
call_command('manage_group', TEST_GROUP, '--remove')
|
|
self.check_groups([])
|
|
|
|
def test_permissions(self):
|
|
"""
|
|
Ensures that permissions are set on the group as specified.
|
|
"""
|
|
self.check_groups([])
|
|
call_command('manage_group', TEST_GROUP, '--permissions', 'auth:Group:add_group')
|
|
self.check_groups([TEST_GROUP])
|
|
self.check_permissions(TEST_GROUP, ['add_group'])
|
|
|
|
# check idempotency
|
|
call_command('manage_group', TEST_GROUP, '--permissions', 'auth:Group:add_group')
|
|
self.check_groups([TEST_GROUP])
|
|
self.check_permissions(TEST_GROUP, ['add_group'])
|
|
|
|
# check adding a permission
|
|
call_command('manage_group', TEST_GROUP, '--permissions', 'auth:Group:add_group', 'auth:Group:change_group')
|
|
self.check_groups([TEST_GROUP])
|
|
self.check_permissions(TEST_GROUP, ['add_group', 'change_group'])
|
|
|
|
# check removing a permission
|
|
call_command('manage_group', TEST_GROUP, '--permissions', 'auth:Group:change_group')
|
|
self.check_groups([TEST_GROUP])
|
|
self.check_permissions(TEST_GROUP, ['change_group'])
|
|
|
|
# check removing all permissions
|
|
call_command('manage_group', TEST_GROUP)
|
|
self.check_groups([TEST_GROUP])
|
|
self.check_permissions(TEST_GROUP, [])
|