From 1e08e9411a9aad40e0e51f4fabb4f106ccc06213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Norman=20J=C3=A4ckel?= Date: Wed, 16 Sep 2015 00:55:27 +0200 Subject: [PATCH] Cleaned up users app. --- openslides/global_settings.py | 9 +- openslides/users/api.py | 10 -- openslides/users/apps.py | 6 +- openslides/users/auth.py | 134 ++++++++---------- openslides/users/exceptions.py | 4 +- .../management/commands/createsuperuser.py | 2 +- openslides/users/models.py | 114 ++++++++------- openslides/users/pdf.py | 5 +- openslides/users/projector.py | 5 +- openslides/users/search_indexes.py | 4 +- openslides/users/serializers.py | 19 +-- openslides/users/signals.py | 14 +- openslides/users/urls.py | 20 +-- openslides/users/views.py | 22 ++- openslides/utils/rest_api.py | 1 + openslides/utils/utils.py | 19 +-- tests/unit/users/test_api.py | 19 --- tests/unit/users/test_auth.py | 39 +---- tests/unit/users/test_models.py | 37 ----- 19 files changed, 175 insertions(+), 308 deletions(-) delete mode 100644 openslides/users/api.py delete mode 100644 tests/unit/users/test_api.py diff --git a/openslides/global_settings.py b/openslides/global_settings.py index 62b15d902..161b62f11 100644 --- a/openslides/global_settings.py +++ b/openslides/global_settings.py @@ -91,13 +91,6 @@ INSTALLED_APPS = ( 'openslides.mediafiles', ) -TEMPLATE_CONTEXT_PROCESSORS = ( - 'openslides.users.auth.auth', - 'django.contrib.messages.context_processors.messages', - 'django.core.context_processors.request', - 'django.core.context_processors.i18n', - 'django.core.context_processors.static', -) CACHES = { 'default': { @@ -175,6 +168,6 @@ TEST_RUNNER = 'openslides.utils.test.OpenSlidesDiscoverRunner' REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', - 'openslides.users.auth.AnonymousAuthentication', + 'openslides.users.auth.RESTFrameworkAnonymousAuthentication', ) } diff --git a/openslides/users/api.py b/openslides/users/api.py deleted file mode 100644 index 2fe0d3106..000000000 --- a/openslides/users/api.py +++ /dev/null @@ -1,10 +0,0 @@ -from .models import Permission - - -def get_protected_perm(): - """ - Returns the permission to manage users. This function is a helper - function used to protect manager users from locking out themselves. - """ - return Permission.objects.get_by_natural_key( - app_label='users', model='user', codename='can_manage') diff --git a/openslides/users/apps.py b/openslides/users/apps.py index 4181d1927..1aac71ca0 100644 --- a/openslides/users/apps.py +++ b/openslides/users/apps.py @@ -10,12 +10,12 @@ class UsersAppConfig(AppConfig): def ready(self): # Load projector elements. - # Do this by just importing all from these files. + # Just import this file. from . import projector # noqa # Import all required stuff. - from openslides.core.signals import config_signal, post_permission_creation - from openslides.utils.rest_api import router + from ..core.signals import config_signal, post_permission_creation + from ..utils.rest_api import router from .signals import create_builtin_groups_and_admin, setup_users_config from .views import GroupViewSet, UserViewSet diff --git a/openslides/users/auth.py b/openslides/users/auth.py index fbc1e73c1..27bd0bfea 100644 --- a/openslides/users/auth.py +++ b/openslides/users/auth.py @@ -1,63 +1,30 @@ from django.contrib.auth import get_user as _get_user from django.contrib.auth import get_user_model from django.contrib.auth.backends import ModelBackend -from django.contrib.auth.context_processors import auth as _auth from django.contrib.auth.models import AnonymousUser as DjangoAnonymousUser from django.contrib.auth.models import Permission from django.db.models import Q from django.utils.functional import SimpleLazyObject from rest_framework.authentication import BaseAuthentication -from openslides.core.config import config +from ..core.config import config -class AnonymousUser(DjangoAnonymousUser): - """ - Class for anonymous user instances, which have the permissions from the - Group 'Anonymous' (pk=1). - """ - - def get_all_permissions(self, obj=None): - """ - Return the permissions a user is granted by his group membership(s). - - Try to return the permissions for the 'Anonymous' group (pk=1). - """ - perms = Permission.objects.filter(group__pk=1) - if perms is None: - return set() - # TODO: test without order_by() - perms = perms.values_list('content_type__app_label', 'codename').order_by() - return set(['%s.%s' % (content_type, codename) for content_type, codename in perms]) - - def has_perm(self, perm, obj=None): - """ - Check if the user has a specific permission - """ - return (perm in self.get_all_permissions()) - - def has_module_perms(self, app_label): - """ - Check if the user has permissions on the module app_label - """ - for perm in self.get_all_permissions(): - if perm[:perm.index('.')] == app_label: - return True - return False - +# Registered users class CustomizedModelBackend(ModelBackend): """ - Customized backend for authentication. Ensures that registered users have - all permission of the group 'Registered' (pk=2). + Customized backend for authentication. Ensures that registered users + have all permissions of the group 'Registered' (pk=2). See + AUTHENTICATION_BACKENDS settings. """ def get_group_permissions(self, user_obj, obj=None): """ Returns a set of permission strings that this user has through his/her groups. """ - # TODO: Refactor this after Django 1.8 release. Add also anonymous - # permission check to this backend. + # TODO: Refactor this after Django 1.8 is minimum requirement. Add + # also anonymous permission check to this backend. if user_obj.is_anonymous() or obj is not None: return set() if not hasattr(user_obj, '_group_perm_cache'): @@ -74,11 +41,61 @@ class CustomizedModelBackend(ModelBackend): return user_obj._group_perm_cache -class AuthenticationMiddleware(object): +# Anonymous users + +class AnonymousUser(DjangoAnonymousUser): + """ + Class for anonymous user instances which have the permissions from the + group 'Anonymous' (pk=1). + """ + def get_all_permissions(self, obj=None): + """ + Returns the permissions a user is granted by his group membership(s). + + Try to return the permissions for the 'Anonymous' group (pk=1). + """ + perms = Permission.objects.filter(group__pk=1) + if perms is None: + return set() + # TODO: Test without order_by() + perms = perms.values_list('content_type__app_label', 'codename').order_by() + return set(['%s.%s' % (content_type, codename) for content_type, codename in perms]) + + def has_perm(self, perm, obj=None): + """ + Checks if the user has a specific permission. + """ + return (perm in self.get_all_permissions()) + + def has_module_perms(self, app_label): + """ + Checks if the user has permissions on the module app_label. + """ + for perm in self.get_all_permissions(): + if perm[:perm.index('.')] == app_label: + return True + return False + + +class RESTFrameworkAnonymousAuthentication(BaseAuthentication): + """ + Authentication class for the Django REST framework. + + Sets the user to the our AnonymousUser but only if + general_system_enable_anonymous is set to True in the config. + """ + + def authenticate(self, request): + if config['general_system_enable_anonymous']: + return (AnonymousUser(), None) + return None + + +class AuthenticationMiddleware: """ Middleware to get the logged in user in users. - Uses AnonymousUser instead of the django anonymous user. + Uses AnonymousUser instead of Django's anonymous user. """ def process_request(self, request): """ @@ -94,20 +111,6 @@ class AuthenticationMiddleware(object): request.user = SimpleLazyObject(lambda: get_user(request)) -class AnonymousAuthentication(BaseAuthentication): - """ - Authentication class for the Django REST framework. - - Sets the user to the our AnonymousUser but only if - general_system_enable_anonymous is set to True in the config. - """ - - def authenticate(self, request): - if config['general_system_enable_anonymous']: - return (AnonymousUser(), None) - return None - - def get_user(request): """ Gets the user from the request. @@ -124,22 +127,3 @@ def get_user(request): return_user = AnonymousUser() request._cached_user = return_user return return_user - - -def auth(request): - """ - Contextmanager to handle auth. - - Uses the django auth context manager to fill the context. - - Alters the attribute user if the user is not authenticated. - """ - # Call the django standard auth function, like 'super()' - context = _auth(request) - - # Change the django anonymous user with our anonymous user if anonymous auth - # is enabled - if config['general_system_enable_anonymous'] and isinstance(context['user'], DjangoAnonymousUser): - context['user'] = AnonymousUser() - - return context diff --git a/openslides/users/exceptions.py b/openslides/users/exceptions.py index 6f0d8ca80..185aa383d 100644 --- a/openslides/users/exceptions.py +++ b/openslides/users/exceptions.py @@ -1,5 +1,5 @@ -from openslides.utils.exceptions import OpenSlidesError +from ..utils.exceptions import OpenSlidesError -class UserError(OpenSlidesError): +class UsersError(OpenSlidesError): pass diff --git a/openslides/users/management/commands/createsuperuser.py b/openslides/users/management/commands/createsuperuser.py index 79b43d847..e6397ab96 100644 --- a/openslides/users/management/commands/createsuperuser.py +++ b/openslides/users/management/commands/createsuperuser.py @@ -1,6 +1,6 @@ from django.core.management.base import NoArgsCommand -from openslides.users.models import User +from ...models import User class Command(NoArgsCommand): diff --git a/openslides/users/models.py b/openslides/users/models.py index d2093c5eb..0abee1e0f 100644 --- a/openslides/users/models.py +++ b/openslides/users/models.py @@ -1,27 +1,29 @@ from random import choice from django.contrib.auth.hashers import make_password -from django.contrib.auth.models import ( # noqa +from django.contrib.auth.models import ( AbstractBaseUser, BaseUserManager, Group, - Permission, PermissionsMixin, ) from django.db import models from django.utils.translation import ugettext_lazy, ugettext_noop -from openslides.core.config import config -from openslides.utils.models import RESTModelMixin - -from .exceptions import UserError +from ..core.config import config +from ..utils.models import RESTModelMixin +from .exceptions import UsersError class UserManager(BaseUserManager): """ - UserManager that creates new users only with a password and a username. + Customized manager that creates new users only with a password and a + username. """ def create_user(self, username, password, **kwargs): + """ + Creates a new user only with a password and a username. + """ user = self.model(username=username, **kwargs) user.set_password(password) user.save(using=self._db) @@ -29,15 +31,15 @@ class UserManager(BaseUserManager): def create_or_reset_admin_user(self): """ - Creates an user with the username admin. If such a user exists, resets - it. The password is (re)set to 'admin'. The user becomes member of the - group 'Staff' (pk=4). + Creates an user with the username 'admin'. If such a user already + exists, resets it. The password is (re)set to 'admin'. The user + becomes member of the group 'Staff' (pk=4). """ try: staff = Group.objects.get(pk=4) except Group.DoesNotExist: - raise UserError("Admin user can not be created or reset because " - "the group 'Staff' is not available.") + raise UsersError("Admin user can not be created or reset because " + "the group 'Staff' (pk=4) is not available.") admin, created = self.get_or_create( username='admin', defaults={'last_name': 'Administrator'}) @@ -60,7 +62,7 @@ class UserManager(BaseUserManager): base_name = first_name or last_name if not base_name: raise ValueError("Either 'first_name' or 'last_name' must not be " - "empty") + "empty.") if not self.filter(username=base_name).exists(): generated_username = base_name @@ -77,7 +79,7 @@ class UserManager(BaseUserManager): def generate_password(self): """ - Generates a random passwort. + Generates a random passwort. Do not use l, o, I, O, 1 or 0. """ chars = 'abcdefghijkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789' size = 8 @@ -86,56 +88,75 @@ class UserManager(BaseUserManager): class User(RESTModelMixin, PermissionsMixin, AbstractBaseUser): """ - Model for users in OpenSlides. A client can login as a user with - credentials. A user can also just be used as representation for a person - in other OpenSlides app like motion submitter or (assignment) election + Model for users in OpenSlides. A client can login as an user with + credentials. An user can also just be used as representation for a person + in other OpenSlides apps like motion submitter or (assignment) election candidates. """ USERNAME_FIELD = 'username' - slide_callback_name = 'user' username = models.CharField( - ugettext_lazy('Username'), max_length=255, unique=True, blank=True) + ugettext_lazy('Username'), + max_length=255, + unique=True, + blank=True) first_name = models.CharField( - ugettext_lazy('First name'), max_length=255, blank=True) + ugettext_lazy('First name'), + max_length=255, + blank=True) last_name = models.CharField( - ugettext_lazy('Last name'), max_length=255, blank=True) + ugettext_lazy('Last name'), + max_length=255, + blank=True) + + # TODO: Try to remove the default argument in the following fields. - # TODO: try to remove the default argument in the following fields structure_level = models.CharField( - max_length=255, blank=True, default='', - verbose_name=ugettext_lazy('Structure level'), + ugettext_lazy('Structure level'), + max_length=255, + blank=True, + default='', help_text=ugettext_lazy('Will be shown after the name.')) title = models.CharField( - max_length=50, blank=True, default='', - verbose_name=ugettext_lazy('Title'), + ugettext_lazy('Title'), + max_length=50, + blank=True, + default='', help_text=ugettext_lazy('Will be shown before the name.')) about_me = models.TextField( - blank=True, default='', verbose_name=ugettext_lazy('About me'), - help_text=ugettext_lazy('Your profile text')) + ugettext_lazy('About me'), + blank=True, + default='', + help_text=ugettext_lazy('Profile text.')) comment = models.TextField( - blank=True, default='', verbose_name=ugettext_lazy('Comment'), + ugettext_lazy('Comment'), + blank=True, + default='', help_text=ugettext_lazy('Only for notes.')) default_password = models.CharField( - max_length=100, blank=True, default='', - verbose_name=ugettext_lazy('Default password')) + ugettext_lazy('Default password'), + max_length=100, + blank=True, + default='') is_active = models.BooleanField( - ugettext_lazy('active'), default=True, + ugettext_lazy('Active'), + default=True, help_text=ugettext_lazy( 'Designates whether this user should be treated as ' - 'active. Unselect this instead of deleting accounts.')) + 'active. Unselect this instead of deleting the account.')) is_present = models.BooleanField( - ugettext_lazy('present'), default=False, - help_text=ugettext_lazy('Designates whether this user is in the room ' - 'or not.')) + ugettext_lazy('Present'), + default=False, + help_text=ugettext_lazy( + 'Designates whether this user is in the room or not.')) objects = UserManager() @@ -145,19 +166,11 @@ class User(RESTModelMixin, PermissionsMixin, AbstractBaseUser): ('can_see_extra_data', ugettext_noop('Can see extra data of users')), ('can_manage', ugettext_noop('Can manage users')), ) - ordering = ('last_name',) + ordering = ('last_name', 'first_name', 'username', ) def __str__(self): return self.get_full_name() - def get_slide_context(self, **context): - """ - Returns the context for the user slide. - """ - # Does not call super. In this case the context would override the name - # 'user'. - return {'shown_user': self} - def get_full_name(self): """ Returns a long form of the name. @@ -166,7 +179,6 @@ class User(RESTModelMixin, PermissionsMixin, AbstractBaseUser): * Professor Dr. Enders, Christoph (Leipzig) """ structure = '(%s)' % self.structure_level if self.structure_level else '' - return ' '.join((self.title, self.get_short_name(), structure)).strip() def get_short_name(self): @@ -190,15 +202,9 @@ class User(RESTModelMixin, PermissionsMixin, AbstractBaseUser): # The user has only a first_name or a last_name or no name else: name = first_name or last_name or self.username - return name - def reset_password(self, password=None): - """ - Reset the password for the user to his default-password. - """ - if password is None: - password = self.default_password - self.set_password(password) + # Return result + return name def get_view_class(self): """ diff --git a/openslides/users/pdf.py b/openslides/users/pdf.py index daad36d72..109d01a30 100644 --- a/openslides/users/pdf.py +++ b/openslides/users/pdf.py @@ -14,9 +14,8 @@ from reportlab.platypus import ( TableStyle, ) -from openslides.core.config import config -from openslides.utils.pdf import stylesheet - +from ..core.config import config +from ..utils.pdf import stylesheet from .models import User diff --git a/openslides/users/projector.py b/openslides/users/projector.py index 2ec339477..418cebc08 100644 --- a/openslides/users/projector.py +++ b/openslides/users/projector.py @@ -1,8 +1,7 @@ from django.utils.translation import ugettext as _ -from openslides.core.exceptions import ProjectorException -from openslides.utils.projector import ProjectorElement, ProjectorRequirement - +from ..core.exceptions import ProjectorException +from ..utils.projector import ProjectorElement, ProjectorRequirement from .models import User from .views import GroupViewSet, UserViewSet diff --git a/openslides/users/search_indexes.py b/openslides/users/search_indexes.py index 6c7ce3702..001277317 100644 --- a/openslides/users/search_indexes.py +++ b/openslides/users/search_indexes.py @@ -6,8 +6,8 @@ from .models import User class Index(indexes.SearchIndex, indexes.Indexable): text = indexes.EdgeNgramField(document=True, use_template=True) text = indexes.EdgeNgramField(document=True, use_template=True) - modelfilter_name = "Users" # verbose_name of model - modelfilter_value = "users.user" # 'app_name.model_name' + modelfilter_name = 'Users' # verbose_name of model + modelfilter_value = 'users.user' # 'app_name.model_name' def get_model(self): return User diff --git a/openslides/users/serializers.py b/openslides/users/serializers.py index 055af49d3..95a86bb79 100644 --- a/openslides/users/serializers.py +++ b/openslides/users/serializers.py @@ -1,15 +1,15 @@ from django.contrib.auth.hashers import make_password +from django.contrib.auth.models import Permission from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy -from openslides.utils.rest_api import ( +from ..utils.rest_api import ( ModelSerializer, PrimaryKeyRelatedField, RelatedField, ValidationError, ) - -from .models import Group, Permission, User +from .models import Group, User class UserShortSerializer(ModelSerializer): @@ -28,7 +28,8 @@ class UserShortSerializer(ModelSerializer): 'last_name', 'structure_level', 'about_me', - 'groups',) + 'groups', + ) class UserFullSerializer(ModelSerializer): @@ -58,7 +59,8 @@ class UserFullSerializer(ModelSerializer): 'comment', 'groups', 'default_password', - 'is_active',) + 'is_active', + ) def validate(self, data): """ @@ -70,7 +72,7 @@ class UserFullSerializer(ModelSerializer): raise ValidationError(_('Username, first name and last name can not all be empty.')) # Generate username. But only if it is not set and the serializer is not - # called in a patch-context. + # called in a PATCH context (partial_update). try: action = self.context['view'].action except (KeyError, AttributeError): @@ -84,7 +86,7 @@ class UserFullSerializer(ModelSerializer): def create(self, validated_data): """ - Creates the user. Sets the default_password. Adds the new user to the + Creates the user. Sets the default password. Adds the new user to the registered group. """ # Prepare setup password. @@ -139,4 +141,5 @@ class GroupSerializer(ModelSerializer): fields = ( 'id', 'name', - 'permissions',) + 'permissions', + ) diff --git a/openslides/users/signals.py b/openslides/users/signals.py index 5a5222099..a5bc12271 100644 --- a/openslides/users/signals.py +++ b/openslides/users/signals.py @@ -1,10 +1,10 @@ +from django.contrib.auth.models import Permission from django.db.models import Q from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy, ugettext_noop -from openslides.core.config import ConfigVariable - -from .models import Group, Permission, User +from ..core.config import ConfigVariable +from .models import Group, User def setup_users_config(sender, **kwargs): @@ -126,9 +126,10 @@ def create_builtin_groups_and_admin(**kwargs): 'users.can_manage', 'users.can_see_extra_data', 'users.can_see_name', ) - permission_dict = {} permission_query = Q() + permission_dict = {} + # Load all permissions for permission_string in permission_strings: app_label, codename = permission_string.split('.') query_part = Q(content_type__app_label=app_label) & Q(codename=codename) @@ -183,11 +184,12 @@ def create_builtin_groups_and_admin(**kwargs): group_staff = Group.objects.create(name=ugettext_noop('Staff'), pk=4) group_staff.permissions.add(*staff_permissions) - # Add users.can_see_name and users.can_see_extra_data permissions + # Add users.can_see_name and users.can_see_extra_data permissions to staff + # group to ensure proper management possibilities # TODO: Remove this redundancy after cleanup of the permission system. group_staff.permissions.add( permission_dict['users.can_see_extra_data'], permission_dict['users.can_see_name']) - # Admin user + # Create or reset admin user User.objects.create_or_reset_admin_user() diff --git a/openslides/users/urls.py b/openslides/users/urls.py index 57c779ea9..cc495fd34 100644 --- a/openslides/users/urls.py +++ b/openslides/users/urls.py @@ -5,16 +5,7 @@ from . import views urlpatterns = patterns( '', - # PDF - url(r'^print/$', - views.UsersListPDF.as_view(), - name='user_listpdf'), - - url(r'^passwords/print/$', - views.UsersPasswordsPDF.as_view(), - name='user_passwordspdf'), - - # auth + # Auth url(r'^login/$', views.UserLoginView.as_view(), name='user_login'), @@ -26,4 +17,13 @@ urlpatterns = patterns( url(r'^whoami/$', views.WhoAmIView.as_view(), name='user_whoami'), + + # PDF + url(r'^print/$', + views.UsersListPDF.as_view(), + name='user_listpdf'), + + url(r'^passwords/print/$', + views.UsersPasswordsPDF.as_view(), + name='user_passwordspdf'), ) diff --git a/openslides/users/views.py b/openslides/users/views.py index b15ba3133..51e45507d 100644 --- a/openslides/users/views.py +++ b/openslides/users/views.py @@ -3,12 +3,10 @@ from django.contrib.auth import logout as auth_logout from django.contrib.auth.forms import AuthenticationForm from django.utils.translation import ugettext as _ from django.utils.translation import ugettext_lazy -from rest_framework import status - -from openslides.core.config import config -from openslides.utils.rest_api import ModelViewSet, Response, detail_route -from openslides.utils.views import APIView, PDFView +from ..core.config import config +from ..utils.rest_api import ModelViewSet, Response, detail_route, status +from ..utils.views import APIView, PDFView from .models import Group, User from .pdf import users_passwords_to_pdf, users_to_pdf from .serializers import ( @@ -185,7 +183,7 @@ class GroupViewSet(ModelViewSet): class UserLoginView(APIView): """ - Login the user via Ajax. + Login the user. """ http_method_names = ['post'] @@ -208,7 +206,7 @@ class UserLoginView(APIView): class UserLogoutView(APIView): """ - Logout the user via Ajax. + Logout the user. """ http_method_names = ['post'] @@ -225,7 +223,7 @@ class WhoAmIView(APIView): def get_context_data(self, **context): """ - Appends the user id into the context. + Appends the user id to the context. Uses None for the anonymous user. """ @@ -238,11 +236,11 @@ class WhoAmIView(APIView): class UsersListPDF(PDFView): """ - Generate the userliste as PDF. + Generate a list of all users as PDF. """ required_permission = 'users.can_see_extra_data' - filename = ugettext_lazy("user-list") - document_title = ugettext_lazy('List of Users') + filename = ugettext_lazy('user-list') + document_title = ugettext_lazy('List of users') def append_to_pdf(self, pdf): """ @@ -256,7 +254,7 @@ class UsersPasswordsPDF(PDFView): Generate the access data welcome paper for all users as PDF. """ required_permission = 'users.can_manage' - filename = ugettext_lazy("User-access-data") + filename = ugettext_lazy('user-access-data') top_space = 0 def build_document(self, pdf_document, story): diff --git a/openslides/utils/rest_api.py b/openslides/utils/rest_api.py index b1d4b8b3f..0e8ddad11 100644 --- a/openslides/utils/rest_api.py +++ b/openslides/utils/rest_api.py @@ -2,6 +2,7 @@ import re from collections import OrderedDict from urllib.parse import urlparse +from rest_framework import status # noqa from rest_framework.decorators import detail_route, list_route # noqa from rest_framework.metadata import SimpleMetadata # noqa from rest_framework.mixins import DestroyModelMixin, UpdateModelMixin # noqa diff --git a/openslides/utils/utils.py b/openslides/utils/utils.py index 05368581f..b2d01f01e 100644 --- a/openslides/utils/utils.py +++ b/openslides/utils/utils.py @@ -1,25 +1,10 @@ import roman -from django.contrib.auth.models import Permission - - -def delete_default_permissions(**kwargs): - """ - Deletes the permissions, django creates by default for the admin. - """ - # TODO: Find a way not to create the permissions in the first place. - # Meta.default_permissions does not work, because django will - # nevertheless create permissions for its own models like "group" - for p in Permission.objects.all(): - if (p.codename.startswith('add') or - p.codename.startswith('delete') or - p.codename.startswith('change')): - p.delete() def to_roman(number): """ - Converts an arabic number within range from 1 to 4999 to the corresponding roman number. - Returns None on error conditions. + Converts an arabic number within range from 1 to 4999 to the + corresponding roman number. Returns None on error conditions. """ try: return roman.toRoman(number) diff --git a/tests/unit/users/test_api.py b/tests/unit/users/test_api.py deleted file mode 100644 index f82beac58..000000000 --- a/tests/unit/users/test_api.py +++ /dev/null @@ -1,19 +0,0 @@ -from unittest import TestCase -from unittest.mock import patch - -from openslides.users.api import get_protected_perm - - -@patch('openslides.users.api.Permission') -class GetProtectedPerm(TestCase): - def test_normal(self, mock_permission): - mock_permission.objects.get_by_natural_key.return_value = 'test_permission' - - value = get_protected_perm() - - mock_permission.objects.get_by_natural_key.assert_called_once_with( - app_label='users', model='user', codename='can_manage') - self.assertEqual( - value, - 'test_permission', - "The function should return the user.can_manage permission") diff --git a/tests/unit/users/test_auth.py b/tests/unit/users/test_auth.py index 7e3d604f3..fe5fa63d0 100644 --- a/tests/unit/users/test_auth.py +++ b/tests/unit/users/test_auth.py @@ -1,7 +1,7 @@ from unittest import TestCase from unittest.mock import MagicMock, patch -from openslides.users.auth import AnonymousUser, auth, get_user +from openslides.users.auth import AnonymousUser, get_user class TestAnonymousUser(TestCase): @@ -98,40 +98,3 @@ class TestGetUser(TestCase): request._cached_user, 'django_anonymous_user', "The django user should be cached") - - -@patch('openslides.users.auth.config') -@patch('openslides.users.auth._auth') -class TestAuth(TestCase): - def test_anonymous_enabled(self, mock_auth, mock_config): - mock_config.__getitem__.return_value = True - request = MagicMock() - mock_auth.return_value = {'user': AnonymousUser()} - - context = auth(request) - - self.assertEqual( - context, - {'user': AnonymousUser()}) - - def test_anonymous_disabled(self, mock_auth, mock_config): - mock_config.__getitem__.return_value = False - request = MagicMock() - mock_auth.return_value = {'user': AnonymousUser()} - - context = auth(request) - - self.assertEqual( - context, - {'user': AnonymousUser()}) - - def test_logged_in_user_in_request(self, mock_auth, mock_config): - mock_config.__getitem__.return_value = True - request = MagicMock() - mock_auth.return_value = {'user': 'logged_in_user'} - - context = auth(request) - - self.assertEqual( - context, - {'user': 'logged_in_user'}) diff --git a/tests/unit/users/test_models.py b/tests/unit/users/test_models.py index 0f2611d5d..497e35fae 100644 --- a/tests/unit/users/test_models.py +++ b/tests/unit/users/test_models.py @@ -18,19 +18,6 @@ class UserTest(TestCase): 'Test Value IJee1yoet1ooGhesh5li', "The str representation of User is not user.get_full_name().") - def test_get_slide_context(self): - """ - Tests, that get_slide_context returns: - - {'shown_user': self} - """ - user = User() - - self.assertEqual( - user.get_slide_context(), - {'shown_user': user}, - "User.get_slide_context returns a wrong context.") - class UserGetFullName(TestCase): def test_get_full_name_with_structure_level_and_title(self): @@ -185,30 +172,6 @@ class UserGetShortName(TestCase): "User.get_short_name() has to strip whitespaces from the name parts.") -class UserResetPassword(TestCase): - def test_reset_password_no_attribute(self): - """ - Tests reset_password with no attribute. - """ - user = User(default_password='test_default_password') - user.set_password = MagicMock() - - user.reset_password() - - user.set_password.assert_called_once_with('test_default_password') - - def test_reset_password_with_attribute(self): - """ - Tests reset_password with no attribute. - """ - user = User(default_password='test_default_password') - user.set_password = MagicMock() - - user.reset_password('test_password') - - user.set_password.assert_called_once_with('test_password') - - class UserManagerTest(TestCase): def test_create_user(self): """