Migration for new permission matrix

This commit is contained in:
Finn Stutzenstein 2016-08-30 09:16:47 +02:00
parent f6ece5f6b3
commit 4ffe2b5a80
4 changed files with 114 additions and 24 deletions

View File

@ -0,0 +1,56 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.9.7 on 2016-08-01 14:54
from __future__ import unicode_literals
from django.core.exceptions import ObjectDoesNotExist
from django.db import migrations
def migrate_groups_and_user_permissions(apps, schema_editor):
"""
This function migrates the database to the new groups logic:
- Rename Group 'Anonymous' (pk=1) to 'Default'
- Rename Group 'Registered users' (pk=2) to 'Previous group Registered'
- Add all users who are not in any group to this group (pk=2)
- Add all permissions of 'Previous group Registered' to all other groups (exclude 'Default')
But only do this migration if:
- there are groups in the database
- the name of the first group is 'Guests'.
"""
User = apps.get_model('users', 'User')
Group = apps.get_model('auth', 'Group')
if Group.objects.exists():
try:
group_default = Group.objects.filter(pk=1)
if group_default.get().name == 'Guests':
group_default.update(name='Default')
group_old_registered = Group.objects.filter(pk=2)
group_old_registered.update(name='Previous group Registered')
group_old_registered = group_old_registered.get()
users = User.objects.all()
for user in users:
if not user.groups.exists():
user.groups.add(group_old_registered.pk)
groups = Group.objects.filter(pk__gt=2)
for group in groups:
for permission in group_old_registered.permissions.all():
group.permissions.add(permission)
except ObjectDoesNotExist:
# If the first or second group doesn't exists, just pass this migraition
pass
class Migration(migrations.Migration):
dependencies = [
('users', '0003_user_number'),
]
operations = [
migrations.RunPython(migrate_groups_and_user_permissions),
]

View File

@ -5,16 +5,17 @@ from django.contrib.auth.models import (
AbstractBaseUser, AbstractBaseUser,
BaseUserManager, BaseUserManager,
Group, Group,
Permission,
PermissionsMixin, PermissionsMixin,
) )
from django.db import models from django.db import models
from django.db.models import Q
from openslides.utils.search import user_name_helper from openslides.utils.search import user_name_helper
from ..core.config import config from ..core.config import config
from ..utils.models import RESTModelMixin from ..utils.models import RESTModelMixin
from .access_permissions import UserAccessPermissions from .access_permissions import UserAccessPermissions
from .exceptions import UsersError
class UserManager(BaseUserManager): class UserManager(BaseUserManager):
@ -35,13 +36,17 @@ class UserManager(BaseUserManager):
""" """
Creates an user with the username 'admin'. If such a user already Creates an user with the username 'admin'. If such a user already
exists, resets it. The password is (re)set to 'admin'. The user exists, resets it. The password is (re)set to 'admin'. The user
becomes member of the group 'Staff' (pk=3). becomes member of the group 'Staff'. The two important permissions
'users.can_see_name' and 'users.can_manage' are added to this group,
so that the admin can manage all other permissions.
""" """
try: query_can_see_name = Q(content_type__app_label='users') & Q(codename='can_see_name')
staff = Group.objects.get(pk=3) query_can_manage = Q(content_type__app_label='users') & Q(codename='can_manage')
except Group.DoesNotExist:
raise UsersError("Admin user can not be created or reset because " staff, _ = Group.objects.get_or_create(name='Staff')
"the group 'Staff' (pk=3) is not available.") staff.permissions.add(Permission.objects.get(query_can_see_name))
staff.permissions.add(Permission.objects.get(query_can_manage))
admin, created = self.get_or_create( admin, created = self.get_or_create(
username='admin', username='admin',
defaults={'last_name': 'Administrator'}) defaults={'last_name': 'Administrator'})

View File

@ -10,8 +10,8 @@ def create_builtin_groups_and_admin(**kwargs):
Creates the builtin user: admin. Creates the builtin user: admin.
""" """
# Check whether the group pk's 1 to 4 are free. # Check whether there are groups in the database.
if Group.objects.filter(pk__in=range(1, 5)).exists(): if Group.objects.exists():
# Do completely nothing if there are already some of our groups in the database. # Do completely nothing if there are already some of our groups in the database.
return return

View File

@ -286,30 +286,26 @@ class UserManagerGeneratePassword(TestCase):
for _ in range(8)]) for _ in range(8)])
@patch('openslides.users.models.Permission')
@patch('openslides.users.models.Group') @patch('openslides.users.models.Group')
class UserManagerCreateOrResetAdminUser(TestCase): class UserManagerCreateOrResetAdminUser(TestCase):
def test_get_admin_group(self, mock_group): def test_add_admin_group(self, mock_group, mock_permission):
""" """
Tests that the Group with pk=3 is added to the admin. Tests that the Group with name='Staff' is added to the admin.
""" """
def mock_side_effect(pk):
if pk == 3:
result = 'mock_staff'
else:
result = ''
return result
admin_user = MagicMock() admin_user = MagicMock()
manager = UserManager() manager = UserManager()
manager.get_or_create = MagicMock(return_value=(admin_user, False)) manager.get_or_create = MagicMock(return_value=(admin_user, False))
mock_group.objects.get.side_effect = mock_side_effect
staff_group = MagicMock(name="Staff")
mock_group.objects.get_or_create = MagicMock(return_value=(staff_group, True))
mock_permission.get = MagicMock()
manager.create_or_reset_admin_user() manager.create_or_reset_admin_user()
mock_group.objects.get.assert_called_once_with(pk=3) admin_user.groups.add.assert_called_once_with(staff_group)
admin_user.groups.add.assert_called_once_with('mock_staff')
def test_password_set_to_admin(self, mock_group): def test_password_set_to_admin(self, mock_group, mock_permission):
""" """
Tests that the password of the admin is set to 'admin'. Tests that the password of the admin is set to 'admin'.
""" """
@ -317,6 +313,10 @@ class UserManagerCreateOrResetAdminUser(TestCase):
manager = UserManager() manager = UserManager()
manager.get_or_create = MagicMock(return_value=(admin_user, False)) manager.get_or_create = MagicMock(return_value=(admin_user, False))
staff_group = MagicMock(name="Staff")
mock_group.objects.get_or_create = MagicMock(return_value=(staff_group, True))
mock_permission.get = MagicMock()
manager.create_or_reset_admin_user() manager.create_or_reset_admin_user()
self.assertEqual( self.assertEqual(
@ -325,7 +325,7 @@ class UserManagerCreateOrResetAdminUser(TestCase):
admin_user.save.assert_called_once_with() admin_user.save.assert_called_once_with()
@patch('openslides.users.models.User') @patch('openslides.users.models.User')
def test_return_value(self, mock_user, mock_group): def test_return_value(self, mock_user, mock_group, mock_permission):
""" """
Tests that the method returns True when a user is created. Tests that the method returns True when a user is created.
""" """
@ -334,6 +334,10 @@ class UserManagerCreateOrResetAdminUser(TestCase):
manager.get_or_create = MagicMock(return_value=(admin_user, True)) manager.get_or_create = MagicMock(return_value=(admin_user, True))
manager.model = mock_user manager.model = mock_user
staff_group = MagicMock(name="Staff")
mock_group.objects.get_or_create = MagicMock(return_value=(staff_group, True))
mock_permission.get = MagicMock()
self.assertEqual( self.assertEqual(
manager.create_or_reset_admin_user(), manager.create_or_reset_admin_user(),
True, True,
@ -341,7 +345,7 @@ class UserManagerCreateOrResetAdminUser(TestCase):
"new user is created.") "new user is created.")
@patch('openslides.users.models.User') @patch('openslides.users.models.User')
def test_attributes_of_created_user(self, mock_user, mock_group): def test_attributes_of_created_user(self, mock_user, mock_group, mock_permission):
""" """
Tests username and last_name of the created admin user. Tests username and last_name of the created admin user.
""" """
@ -350,6 +354,10 @@ class UserManagerCreateOrResetAdminUser(TestCase):
manager.get_or_create = MagicMock(return_value=(admin_user, True)) manager.get_or_create = MagicMock(return_value=(admin_user, True))
manager.model = mock_user manager.model = mock_user
staff_group = MagicMock(name="Staff")
mock_group.objects.get_or_create = MagicMock(return_value=(staff_group, True))
mock_permission.get = MagicMock()
manager.create_or_reset_admin_user() manager.create_or_reset_admin_user()
self.assertEqual( self.assertEqual(
@ -360,3 +368,24 @@ class UserManagerCreateOrResetAdminUser(TestCase):
admin_user.last_name, admin_user.last_name,
'Administrator', 'Administrator',
"The last_name of a new created admin should be 'Administrator'.") "The last_name of a new created admin should be 'Administrator'.")
def test_get_permissions(self, mock_group, mock_permission):
"""
Tests if two permissions are get
"""
admin_user = MagicMock()
manager = UserManager()
manager.get_or_create = MagicMock(return_value=(admin_user, True))
staff_group = MagicMock(name="Staff")
mock_group.objects.get_or_create = MagicMock(return_value=(staff_group, True))
permission_mock = MagicMock(name="test permission")
mock_permission.objects.get = MagicMock(return_value=permission_mock)
manager.create_or_reset_admin_user()
self.assertEqual(
mock_permission.objects.get.call_count,
2,
"Permission.get should be called two times")