Merge pull request #2909 from ostcar/rework_auth
Created a function to convert anything possible to a user-collection-element or None
This commit is contained in:
commit
8234340a0c
@ -102,6 +102,7 @@ Other:
|
|||||||
- Accelerated startup process (send all data to the client after login).
|
- Accelerated startup process (send all data to the client after login).
|
||||||
- Added function utils.auth.anonymous_is_enabled which returns true, if it is.
|
- Added function utils.auth.anonymous_is_enabled which returns true, if it is.
|
||||||
- Changed has_perm to support an user id or None (for anyonmous) as first argument.
|
- Changed has_perm to support an user id or None (for anyonmous) as first argument.
|
||||||
|
- Removed our AnonymousUser. Make sure not to use user.has_perm() anymore.
|
||||||
|
|
||||||
|
|
||||||
Version 2.0 (2016-04-18)
|
Version 2.0 (2016-04-18)
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.contrib.auth.models import AnonymousUser
|
||||||
from django.contrib.contenttypes.fields import GenericForeignKey
|
from django.contrib.contenttypes.fields import GenericForeignKey
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
@ -14,7 +15,6 @@ from openslides.utils.exceptions import OpenSlidesError
|
|||||||
from openslides.utils.models import RESTModelMixin
|
from openslides.utils.models import RESTModelMixin
|
||||||
from openslides.utils.utils import to_roman
|
from openslides.utils.utils import to_roman
|
||||||
|
|
||||||
from ..utils.auth import DjangoAnonymousUser
|
|
||||||
from .access_permissions import ItemAccessPermissions
|
from .access_permissions import ItemAccessPermissions
|
||||||
|
|
||||||
|
|
||||||
@ -340,7 +340,7 @@ class SpeakerManager(models.Manager):
|
|||||||
if self.filter(user=user, item=item, begin_time=None).exists():
|
if self.filter(user=user, item=item, begin_time=None).exists():
|
||||||
raise OpenSlidesError(
|
raise OpenSlidesError(
|
||||||
_('{user} is already on the list of speakers.').format(user=user))
|
_('{user} is already on the list of speakers.').format(user=user))
|
||||||
if isinstance(user, DjangoAnonymousUser):
|
if isinstance(user, AnonymousUser):
|
||||||
raise OpenSlidesError(
|
raise OpenSlidesError(
|
||||||
_('An anonymous user can not be on lists of speakers.'))
|
_('An anonymous user can not be on lists of speakers.'))
|
||||||
weight = (self.filter(item=item).aggregate(
|
weight = (self.filter(item=item).aggregate(
|
||||||
|
@ -16,6 +16,7 @@ from openslides.utils.rest_api import (
|
|||||||
list_route,
|
list_route,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from ..utils.auth import has_perm
|
||||||
from .access_permissions import ItemAccessPermissions
|
from .access_permissions import ItemAccessPermissions
|
||||||
from .models import Item, Speaker
|
from .models import Item, Speaker
|
||||||
|
|
||||||
@ -39,16 +40,16 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
elif self.action in ('metadata', 'manage_speaker', 'tree'):
|
elif self.action in ('metadata', 'manage_speaker', 'tree'):
|
||||||
result = self.request.user.has_perm('agenda.can_see')
|
result = has_perm(self.request.user, 'agenda.can_see')
|
||||||
# For manage_speaker and tree requests the rest of the check is
|
# For manage_speaker and tree requests the rest of the check is
|
||||||
# done in the specific method. See below.
|
# done in the specific method. See below.
|
||||||
elif self.action in ('partial_update', 'update'):
|
elif self.action in ('partial_update', 'update'):
|
||||||
result = (self.request.user.has_perm('agenda.can_see') and
|
result = (has_perm(self.request.user, 'agenda.can_see') and
|
||||||
self.request.user.has_perm('agenda.can_see_hidden_items') and
|
has_perm(self.request.user, 'agenda.can_see_hidden_items') and
|
||||||
self.request.user.has_perm('agenda.can_manage'))
|
has_perm(self.request.user, 'agenda.can_manage'))
|
||||||
elif self.action in ('speak', 'sort_speakers', 'numbering'):
|
elif self.action in ('speak', 'sort_speakers', 'numbering'):
|
||||||
result = (self.request.user.has_perm('agenda.can_see') and
|
result = (has_perm(self.request.user, 'agenda.can_see') and
|
||||||
self.request.user.has_perm('agenda.can_manage'))
|
has_perm(self.request.user, 'agenda.can_manage'))
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -80,14 +81,14 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
# Check permissions and other conditions. Get user instance.
|
# Check permissions and other conditions. Get user instance.
|
||||||
if user_id is None:
|
if user_id is None:
|
||||||
# Add oneself
|
# Add oneself
|
||||||
if not self.request.user.has_perm('agenda.can_be_speaker'):
|
if not has_perm(self.request.user, 'agenda.can_be_speaker'):
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
if item.speaker_list_closed:
|
if item.speaker_list_closed:
|
||||||
raise ValidationError({'detail': _('The list of speakers is closed.')})
|
raise ValidationError({'detail': _('The list of speakers is closed.')})
|
||||||
user = self.request.user
|
user = self.request.user
|
||||||
else:
|
else:
|
||||||
# Add someone else.
|
# Add someone else.
|
||||||
if not self.request.user.has_perm('agenda.can_manage'):
|
if not has_perm(self.request.user, 'agenda.can_manage'):
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
try:
|
try:
|
||||||
user = get_user_model().objects.get(pk=int(user_id))
|
user = get_user_model().objects.get(pk=int(user_id))
|
||||||
@ -123,7 +124,7 @@ class ItemViewSet(ListModelMixin, RetrieveModelMixin, UpdateModelMixin, GenericV
|
|||||||
message = _('You are successfully removed from the list of speakers.')
|
message = _('You are successfully removed from the list of speakers.')
|
||||||
else:
|
else:
|
||||||
# Remove someone else.
|
# Remove someone else.
|
||||||
if not self.request.user.has_perm('agenda.can_manage'):
|
if not has_perm(self.request.user, 'agenda.can_manage'):
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
if type(speaker_ids) is int:
|
if type(speaker_ids) is int:
|
||||||
speaker_ids = [speaker_ids]
|
speaker_ids = [speaker_ids]
|
||||||
|
@ -13,6 +13,7 @@ from openslides.utils.rest_api import (
|
|||||||
detail_route,
|
detail_route,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
from ..utils.auth import has_perm
|
||||||
from .access_permissions import AssignmentAccessPermissions
|
from .access_permissions import AssignmentAccessPermissions
|
||||||
from .models import Assignment, AssignmentPoll, AssignmentRelatedUser
|
from .models import Assignment, AssignmentPoll, AssignmentRelatedUser
|
||||||
from .serializers import AssignmentAllPollSerializer
|
from .serializers import AssignmentAllPollSerializer
|
||||||
@ -42,14 +43,14 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
result = True
|
result = True
|
||||||
elif self.action in ('create', 'partial_update', 'update', 'destroy',
|
elif self.action in ('create', 'partial_update', 'update', 'destroy',
|
||||||
'mark_elected', 'create_poll', 'sort_related_users'):
|
'mark_elected', 'create_poll', 'sort_related_users'):
|
||||||
result = (self.request.user.has_perm('assignments.can_see') and
|
result = (has_perm(self.request.user, 'assignments.can_see') and
|
||||||
self.request.user.has_perm('assignments.can_manage'))
|
has_perm(self.request.user, 'assignments.can_manage'))
|
||||||
elif self.action == 'candidature_self':
|
elif self.action == 'candidature_self':
|
||||||
result = (self.request.user.has_perm('assignments.can_see') and
|
result = (has_perm(self.request.user, 'assignments.can_see') and
|
||||||
self.request.user.has_perm('assignments.can_nominate_self'))
|
has_perm(self.request.user, 'assignments.can_nominate_self'))
|
||||||
elif self.action == 'candidature_other':
|
elif self.action == 'candidature_other':
|
||||||
result = (self.request.user.has_perm('assignments.can_see') and
|
result = (has_perm(self.request.user, 'assignments.can_see') and
|
||||||
self.request.user.has_perm('assignments.can_nominate_other'))
|
has_perm(self.request.user, 'assignments.can_nominate_other'))
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -73,7 +74,7 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
def nominate_self(self, request, assignment):
|
def nominate_self(self, request, assignment):
|
||||||
if assignment.phase == assignment.PHASE_FINISHED:
|
if assignment.phase == assignment.PHASE_FINISHED:
|
||||||
raise ValidationError({'detail': _('You can not candidate to this election because it is finished.')})
|
raise ValidationError({'detail': _('You can not candidate to this election because it is finished.')})
|
||||||
if assignment.phase == assignment.PHASE_VOTING and not request.user.has_perm('assignments.can_manage'):
|
if assignment.phase == assignment.PHASE_VOTING and not has_perm(request.user, 'assignments.can_manage'):
|
||||||
# To nominate self during voting you have to be a manager.
|
# To nominate self during voting you have to be a manager.
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
# If the request.user is already a candidate he can nominate himself nevertheless.
|
# If the request.user is already a candidate he can nominate himself nevertheless.
|
||||||
@ -84,7 +85,7 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
# Withdraw candidature.
|
# Withdraw candidature.
|
||||||
if assignment.phase == assignment.PHASE_FINISHED:
|
if assignment.phase == assignment.PHASE_FINISHED:
|
||||||
raise ValidationError({'detail': _('You can not withdraw your candidature to this election because it is finished.')})
|
raise ValidationError({'detail': _('You can not withdraw your candidature to this election because it is finished.')})
|
||||||
if assignment.phase == assignment.PHASE_VOTING and not request.user.has_perm('assignments.can_manage'):
|
if assignment.phase == assignment.PHASE_VOTING and not has_perm(request.user, 'assignments.can_manage'):
|
||||||
# To withdraw self during voting you have to be a manager.
|
# To withdraw self during voting you have to be a manager.
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
if not assignment.is_candidate(request.user):
|
if not assignment.is_candidate(request.user):
|
||||||
@ -133,7 +134,7 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
if assignment.phase == assignment.PHASE_FINISHED:
|
if assignment.phase == assignment.PHASE_FINISHED:
|
||||||
detail = _('You can not nominate someone to this election because it is finished.')
|
detail = _('You can not nominate someone to this election because it is finished.')
|
||||||
raise ValidationError({'detail': detail})
|
raise ValidationError({'detail': detail})
|
||||||
if assignment.phase == assignment.PHASE_VOTING and not request.user.has_perm('assignments.can_manage'):
|
if assignment.phase == assignment.PHASE_VOTING and not has_perm(request.user, 'assignments.can_manage'):
|
||||||
# To nominate another user during voting you have to be a manager.
|
# To nominate another user during voting you have to be a manager.
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
if assignment.is_candidate(user):
|
if assignment.is_candidate(user):
|
||||||
@ -143,7 +144,7 @@ class AssignmentViewSet(ModelViewSet):
|
|||||||
|
|
||||||
def delete_other(self, request, user, assignment):
|
def delete_other(self, request, user, assignment):
|
||||||
# To delete candidature status you have to be a manager.
|
# To delete candidature status you have to be a manager.
|
||||||
if not request.user.has_perm('assignments.can_manage'):
|
if not has_perm(request.user, 'assignments.can_manage'):
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
if assignment.phase == assignment.PHASE_FINISHED:
|
if assignment.phase == assignment.PHASE_FINISHED:
|
||||||
detail = _("You can not delete someone's candidature to this election because it is finished.")
|
detail = _("You can not delete someone's candidature to this election because it is finished.")
|
||||||
@ -243,5 +244,5 @@ class AssignmentPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet)
|
|||||||
"""
|
"""
|
||||||
Returns True if the user has required permissions.
|
Returns True if the user has required permissions.
|
||||||
"""
|
"""
|
||||||
return (self.request.user.has_perm('assignments.can_see') and
|
return (has_perm(self.request.user, 'assignments.can_see') and
|
||||||
self.request.user.has_perm('assignments.can_manage'))
|
has_perm(self.request.user, 'assignments.can_manage'))
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
from django.contrib.auth.models import AnonymousUser
|
||||||
|
|
||||||
from ..utils.access_permissions import BaseAccessPermissions
|
from ..utils.access_permissions import BaseAccessPermissions
|
||||||
from ..utils.auth import DjangoAnonymousUser, anonymous_is_enabled, has_perm
|
from ..utils.auth import anonymous_is_enabled, has_perm
|
||||||
|
|
||||||
|
|
||||||
class ProjectorAccessPermissions(BaseAccessPermissions):
|
class ProjectorAccessPermissions(BaseAccessPermissions):
|
||||||
@ -31,7 +33,7 @@ class TagAccessPermissions(BaseAccessPermissions):
|
|||||||
"""
|
"""
|
||||||
# Every authenticated user can retrieve tags. Anonymous users can do
|
# Every authenticated user can retrieve tags. Anonymous users can do
|
||||||
# so if they are enabled.
|
# so if they are enabled.
|
||||||
return not isinstance(user, DjangoAnonymousUser) or anonymous_is_enabled()
|
return not isinstance(user, AnonymousUser) or anonymous_is_enabled()
|
||||||
|
|
||||||
def get_serializer_class(self, user=None):
|
def get_serializer_class(self, user=None):
|
||||||
"""
|
"""
|
||||||
@ -112,7 +114,7 @@ class ConfigAccessPermissions(BaseAccessPermissions):
|
|||||||
"""
|
"""
|
||||||
# Every authenticated user can see the metadata and list or retrieve
|
# Every authenticated user can see the metadata and list or retrieve
|
||||||
# the config. Anonymous users can do so if they are enabled.
|
# the config. Anonymous users can do so if they are enabled.
|
||||||
return not isinstance(user, DjangoAnonymousUser) or anonymous_is_enabled()
|
return not isinstance(user, AnonymousUser) or anonymous_is_enabled()
|
||||||
|
|
||||||
def get_full_data(self, instance):
|
def get_full_data(self, instance):
|
||||||
"""
|
"""
|
||||||
|
@ -17,7 +17,7 @@ from django.utils.translation import ugettext as _
|
|||||||
|
|
||||||
from .. import __version__ as version
|
from .. import __version__ as version
|
||||||
from ..utils import views as utils_views
|
from ..utils import views as utils_views
|
||||||
from ..utils.auth import anonymous_is_enabled
|
from ..utils.auth import anonymous_is_enabled, has_perm
|
||||||
from ..utils.autoupdate import inform_changed_data, inform_deleted_data
|
from ..utils.autoupdate import inform_changed_data, inform_deleted_data
|
||||||
from ..utils.collection import Collection, CollectionElement
|
from ..utils.collection import Collection, CollectionElement
|
||||||
from ..utils.plugins import (
|
from ..utils.plugins import (
|
||||||
@ -213,15 +213,15 @@ class ProjectorViewSet(ModelViewSet):
|
|||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
elif self.action == 'metadata':
|
elif self.action == 'metadata':
|
||||||
result = self.request.user.has_perm('core.can_see_projector')
|
result = has_perm(self.request.user, 'core.can_see_projector')
|
||||||
elif self.action in (
|
elif self.action in (
|
||||||
'create', 'update', 'partial_update', 'destroy',
|
'create', 'update', 'partial_update', 'destroy',
|
||||||
'activate_elements', 'prune_elements', 'update_elements', 'deactivate_elements', 'clear_elements',
|
'activate_elements', 'prune_elements', 'update_elements', 'deactivate_elements', 'clear_elements',
|
||||||
'control_view', 'set_resolution', 'set_scroll', 'control_blank', 'broadcast',
|
'control_view', 'set_resolution', 'set_scroll', 'control_blank', 'broadcast',
|
||||||
'set_projectiondefault',
|
'set_projectiondefault',
|
||||||
):
|
):
|
||||||
result = (self.request.user.has_perm('core.can_see_projector') and
|
result = (has_perm(self.request.user, 'core.can_see_projector') and
|
||||||
self.request.user.has_perm('core.can_manage_projector'))
|
has_perm(self.request.user, 'core.can_manage_projector'))
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -576,7 +576,7 @@ class TagViewSet(ModelViewSet):
|
|||||||
# Anonymous users can do so if they are enabled.
|
# Anonymous users can do so if they are enabled.
|
||||||
result = self.request.user.is_authenticated() or anonymous_is_enabled()
|
result = self.request.user.is_authenticated() or anonymous_is_enabled()
|
||||||
elif self.action in ('create', 'update', 'destroy'):
|
elif self.action in ('create', 'update', 'destroy'):
|
||||||
result = self.request.user.has_perm('core.can_manage_tags')
|
result = has_perm(self.request.user, 'core.can_manage_tags')
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -633,7 +633,7 @@ class ConfigViewSet(ViewSet):
|
|||||||
# enabled.
|
# enabled.
|
||||||
result = self.request.user.is_authenticated() or anonymous_is_enabled()
|
result = self.request.user.is_authenticated() or anonymous_is_enabled()
|
||||||
elif self.action == 'update':
|
elif self.action == 'update':
|
||||||
result = self.request.user.has_perm('core.can_manage_config')
|
result = has_perm(self.request.user, 'core.can_manage_config')
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -705,11 +705,11 @@ class ChatMessageViewSet(ModelViewSet):
|
|||||||
# group has the permission core.can_use_chat.
|
# group has the permission core.can_use_chat.
|
||||||
result = (
|
result = (
|
||||||
self.request.user.is_authenticated() and
|
self.request.user.is_authenticated() and
|
||||||
self.request.user.has_perm('core.can_use_chat'))
|
has_perm(self.request.user, 'core.can_use_chat'))
|
||||||
elif self.action == 'clear':
|
elif self.action == 'clear':
|
||||||
result = (
|
result = (
|
||||||
self.request.user.has_perm('core.can_use_chat') and
|
has_perm(self.request.user, 'core.can_use_chat') and
|
||||||
self.request.user.has_perm('core.can_manage_chat'))
|
has_perm(self.request.user, 'core.can_manage_chat'))
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -754,7 +754,7 @@ class ProjectorMessageViewSet(ModelViewSet):
|
|||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
elif self.action in ('create', 'update', 'destroy'):
|
elif self.action in ('create', 'update', 'destroy'):
|
||||||
result = self.request.user.has_perm('core.can_manage_projector')
|
result = has_perm(self.request.user, 'core.can_manage_projector')
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -776,7 +776,7 @@ class CountdownViewSet(ModelViewSet):
|
|||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
elif self.action in ('create', 'update', 'destroy'):
|
elif self.action in ('create', 'update', 'destroy'):
|
||||||
result = self.request.user.has_perm('core.can_manage_projector')
|
result = has_perm(self.request.user, 'core.can_manage_projector')
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
|
@ -93,10 +93,6 @@ STATICFILES_DIRS = [
|
|||||||
|
|
||||||
AUTH_USER_MODEL = 'users.User'
|
AUTH_USER_MODEL = 'users.User'
|
||||||
|
|
||||||
AUTHENTICATION_BACKENDS = [
|
|
||||||
'openslides.utils.auth.CustomizedModelBackend',
|
|
||||||
]
|
|
||||||
|
|
||||||
SESSION_COOKIE_NAME = 'OpenSlidesSessionID'
|
SESSION_COOKIE_NAME = 'OpenSlidesSessionID'
|
||||||
|
|
||||||
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
|
SESSION_EXPIRE_AT_BROWSER_CLOSE = True
|
||||||
@ -135,17 +131,6 @@ CACHES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# Django REST framework
|
|
||||||
# http://www.django-rest-framework.org/api-guide/settings/
|
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
|
||||||
'DEFAULT_AUTHENTICATION_CLASSES': (
|
|
||||||
'rest_framework.authentication.SessionAuthentication',
|
|
||||||
'openslides.utils.auth.RESTFrameworkAnonymousAuthentication',
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# Django Channels
|
# Django Channels
|
||||||
# http://channels.readthedocs.io/en/latest/
|
# http://channels.readthedocs.io/en/latest/
|
||||||
|
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
from ..utils.auth import has_perm
|
||||||
from ..utils.rest_api import ModelViewSet, ValidationError
|
from ..utils.rest_api import ModelViewSet, ValidationError
|
||||||
from .access_permissions import MediafileAccessPermissions
|
from .access_permissions import MediafileAccessPermissions
|
||||||
from .models import Mediafile
|
from .models import Mediafile
|
||||||
@ -22,17 +23,17 @@ class MediafileViewSet(ModelViewSet):
|
|||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
elif self.action == 'metadata':
|
elif self.action == 'metadata':
|
||||||
result = self.request.user.has_perm('mediafiles.can_see')
|
result = has_perm(self.request.user, 'mediafiles.can_see')
|
||||||
elif self.action == 'create':
|
elif self.action == 'create':
|
||||||
result = (self.request.user.has_perm('mediafiles.can_see') and
|
result = (has_perm(self.request.user, 'mediafiles.can_see') and
|
||||||
self.request.user.has_perm('mediafiles.can_upload'))
|
has_perm(self.request.user, 'mediafiles.can_upload'))
|
||||||
elif self.action in ('partial_update', 'update'):
|
elif self.action in ('partial_update', 'update'):
|
||||||
result = (self.request.user.has_perm('mediafiles.can_see') and
|
result = (has_perm(self.request.user, 'mediafiles.can_see') and
|
||||||
self.request.user.has_perm('mediafiles.can_upload') and
|
has_perm(self.request.user, 'mediafiles.can_upload') and
|
||||||
self.request.user.has_perm('mediafiles.can_manage'))
|
has_perm(self.request.user, 'mediafiles.can_manage'))
|
||||||
elif self.action == 'destroy':
|
elif self.action == 'destroy':
|
||||||
result = (self.request.user.has_perm('mediafiles.can_see') and
|
result = (has_perm(self.request.user, 'mediafiles.can_see') and
|
||||||
self.request.user.has_perm('mediafiles.can_manage'))
|
has_perm(self.request.user, 'mediafiles.can_manage'))
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -44,7 +45,7 @@ class MediafileViewSet(ModelViewSet):
|
|||||||
# Check permission to check if the uploader has to be changed.
|
# Check permission to check if the uploader has to be changed.
|
||||||
uploader_id = self.request.data.get('uploader_id')
|
uploader_id = self.request.data.get('uploader_id')
|
||||||
if (uploader_id and
|
if (uploader_id and
|
||||||
not request.user.has_perm('mediafiles.can_manage') and
|
not has_perm(request.user, 'mediafiles.can_manage') and
|
||||||
str(self.request.user.pk) != str(uploader_id)):
|
str(self.request.user.pk) != str(uploader_id)):
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
if not self.request.data.get('mediafile'):
|
if not self.request.data.get('mediafile'):
|
||||||
|
@ -9,6 +9,7 @@ from django.utils.translation import ugettext_noop
|
|||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
|
|
||||||
from ..core.config import config
|
from ..core.config import config
|
||||||
|
from ..utils.auth import has_perm
|
||||||
from ..utils.autoupdate import inform_changed_data
|
from ..utils.autoupdate import inform_changed_data
|
||||||
from ..utils.rest_api import (
|
from ..utils.rest_api import (
|
||||||
DestroyModelMixin,
|
DestroyModelMixin,
|
||||||
@ -61,20 +62,20 @@ class MotionViewSet(ModelViewSet):
|
|||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
elif self.action in ('metadata', 'partial_update', 'update'):
|
elif self.action in ('metadata', 'partial_update', 'update'):
|
||||||
result = self.request.user.has_perm('motions.can_see')
|
result = has_perm(self.request.user, 'motions.can_see')
|
||||||
# For partial_update and update requests the rest of the check is
|
# For partial_update and update requests the rest of the check is
|
||||||
# done in the update method. See below.
|
# done in the update method. See below.
|
||||||
elif self.action == 'create':
|
elif self.action == 'create':
|
||||||
result = (self.request.user.has_perm('motions.can_see') and
|
result = (has_perm(self.request.user, 'motions.can_see') and
|
||||||
self.request.user.has_perm('motions.can_create') and
|
has_perm(self.request.user, 'motions.can_create') and
|
||||||
(not config['motions_stop_submitting'] or
|
(not config['motions_stop_submitting'] or
|
||||||
self.request.user.has_perm('motions.can_manage')))
|
has_perm(self.request.user, 'motions.can_manage')))
|
||||||
elif self.action in ('destroy', 'manage_version', 'set_state', 'set_recommendation', 'create_poll'):
|
elif self.action in ('destroy', 'manage_version', 'set_state', 'set_recommendation', 'create_poll'):
|
||||||
result = (self.request.user.has_perm('motions.can_see') and
|
result = (has_perm(self.request.user, 'motions.can_see') and
|
||||||
self.request.user.has_perm('motions.can_manage'))
|
has_perm(self.request.user, 'motions.can_manage'))
|
||||||
elif self.action == 'support':
|
elif self.action == 'support':
|
||||||
result = (self.request.user.has_perm('motions.can_see') and
|
result = (has_perm(self.request.user, 'motions.can_see') and
|
||||||
self.request.user.has_perm('motions.can_support'))
|
has_perm(self.request.user, 'motions.can_support'))
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -84,7 +85,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
Customized view endpoint to create a new motion.
|
Customized view endpoint to create a new motion.
|
||||||
"""
|
"""
|
||||||
# Check permission to send some data.
|
# Check permission to send some data.
|
||||||
if not request.user.has_perm('motions.can_manage'):
|
if not has_perm(request.user, 'motions.can_manage'):
|
||||||
whitelist = (
|
whitelist = (
|
||||||
'title',
|
'title',
|
||||||
'text',
|
'text',
|
||||||
@ -97,7 +98,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
|
|
||||||
# Check permission to send comment data.
|
# Check permission to send comment data.
|
||||||
if not request.user.has_perm('motions.can_see_and_manage_comments'):
|
if not has_perm(request.user, 'motions.can_see_and_manage_comments'):
|
||||||
try:
|
try:
|
||||||
# Ignore comments data if user is not allowed to send comments.
|
# Ignore comments data if user is not allowed to send comments.
|
||||||
del request.data['comments']
|
del request.data['comments']
|
||||||
@ -128,13 +129,13 @@ class MotionViewSet(ModelViewSet):
|
|||||||
motion = self.get_object()
|
motion = self.get_object()
|
||||||
|
|
||||||
# Check permissions.
|
# Check permissions.
|
||||||
if (not request.user.has_perm('motions.can_manage') and
|
if (not has_perm(request.user, 'motions.can_manage') and
|
||||||
not (motion.is_submitter(request.user) and
|
not (motion.is_submitter(request.user) and
|
||||||
motion.state.allow_submitter_edit)):
|
motion.state.allow_submitter_edit)):
|
||||||
self.permission_denied(request)
|
self.permission_denied(request)
|
||||||
|
|
||||||
# Check permission to send only some data.
|
# Check permission to send only some data.
|
||||||
if not request.user.has_perm('motions.can_manage'):
|
if not has_perm(request.user, 'motions.can_manage'):
|
||||||
whitelist = (
|
whitelist = (
|
||||||
'title',
|
'title',
|
||||||
'text',
|
'text',
|
||||||
@ -144,7 +145,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
if key not in whitelist:
|
if key not in whitelist:
|
||||||
# Non-staff users are allowed to send only some data. Ignore other data.
|
# Non-staff users are allowed to send only some data. Ignore other data.
|
||||||
del request.data[key]
|
del request.data[key]
|
||||||
if not request.user.has_perm('motions.can_see_and_manage_comments'):
|
if not has_perm(request.user, 'motions.can_see_and_manage_comments'):
|
||||||
try:
|
try:
|
||||||
del request.data['comments']
|
del request.data['comments']
|
||||||
except KeyError:
|
except KeyError:
|
||||||
@ -163,7 +164,7 @@ class MotionViewSet(ModelViewSet):
|
|||||||
# TODO: Log if a version was updated.
|
# TODO: Log if a version was updated.
|
||||||
updated_motion.write_log([ugettext_noop('Motion updated')], request.user)
|
updated_motion.write_log([ugettext_noop('Motion updated')], request.user)
|
||||||
if (config['motions_remove_supporters'] and updated_motion.state.allow_support and
|
if (config['motions_remove_supporters'] and updated_motion.state.allow_support and
|
||||||
not request.user.has_perm('motions.can_manage')):
|
not has_perm(request.user, 'motions.can_manage')):
|
||||||
updated_motion.supporters.clear()
|
updated_motion.supporters.clear()
|
||||||
updated_motion.write_log([ugettext_noop('All supporters removed')], request.user)
|
updated_motion.write_log([ugettext_noop('All supporters removed')], request.user)
|
||||||
return Response(serializer.data)
|
return Response(serializer.data)
|
||||||
@ -352,8 +353,8 @@ class MotionPollViewSet(UpdateModelMixin, DestroyModelMixin, GenericViewSet):
|
|||||||
"""
|
"""
|
||||||
Returns True if the user has required permissions.
|
Returns True if the user has required permissions.
|
||||||
"""
|
"""
|
||||||
return (self.request.user.has_perm('motions.can_see') and
|
return (has_perm(self.request.user, 'motions.can_see') and
|
||||||
self.request.user.has_perm('motions.can_manage'))
|
has_perm(self.request.user, 'motions.can_manage'))
|
||||||
|
|
||||||
|
|
||||||
class MotionChangeRecommendationViewSet(ModelViewSet):
|
class MotionChangeRecommendationViewSet(ModelViewSet):
|
||||||
@ -373,9 +374,9 @@ class MotionChangeRecommendationViewSet(ModelViewSet):
|
|||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
elif self.action == 'metadata':
|
elif self.action == 'metadata':
|
||||||
result = self.request.user.has_perm('motions.can_see')
|
result = has_perm(self.request.user, 'motions.can_see')
|
||||||
elif self.action in ('create', 'destroy', 'partial_update', 'update'):
|
elif self.action in ('create', 'destroy', 'partial_update', 'update'):
|
||||||
result = self.request.user.has_perm('motions.can_manage')
|
result = has_perm(self.request.user, 'motions.can_manage')
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -398,10 +399,10 @@ class CategoryViewSet(ModelViewSet):
|
|||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
elif self.action == 'metadata':
|
elif self.action == 'metadata':
|
||||||
result = self.request.user.has_perm('motions.can_see')
|
result = has_perm(self.request.user, 'motions.can_see')
|
||||||
elif self.action in ('create', 'partial_update', 'update', 'destroy', 'numbering'):
|
elif self.action in ('create', 'partial_update', 'update', 'destroy', 'numbering'):
|
||||||
result = (self.request.user.has_perm('motions.can_see') and
|
result = (has_perm(self.request.user, 'motions.can_see') and
|
||||||
self.request.user.has_perm('motions.can_manage'))
|
has_perm(self.request.user, 'motions.can_manage'))
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -511,10 +512,10 @@ class MotionBlockViewSet(ModelViewSet):
|
|||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
elif self.action == 'metadata':
|
elif self.action == 'metadata':
|
||||||
result = self.request.user.has_perm('motions.can_see')
|
result = has_perm(self.request.user, 'motions.can_see')
|
||||||
elif self.action in ('create', 'partial_update', 'update', 'destroy', 'follow_recommendations'):
|
elif self.action in ('create', 'partial_update', 'update', 'destroy', 'follow_recommendations'):
|
||||||
result = (self.request.user.has_perm('motions.can_see') and
|
result = (has_perm(self.request.user, 'motions.can_see') and
|
||||||
self.request.user.has_perm('motions.can_manage'))
|
has_perm(self.request.user, 'motions.can_manage'))
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -559,10 +560,10 @@ class WorkflowViewSet(ModelViewSet):
|
|||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
elif self.action == 'metadata':
|
elif self.action == 'metadata':
|
||||||
result = self.request.user.has_perm('motions.can_see')
|
result = has_perm(self.request.user, 'motions.can_see')
|
||||||
elif self.action in ('create', 'partial_update', 'update', 'destroy'):
|
elif self.action in ('create', 'partial_update', 'update', 'destroy'):
|
||||||
result = (self.request.user.has_perm('motions.can_see') and
|
result = (has_perm(self.request.user, 'motions.can_see') and
|
||||||
self.request.user.has_perm('motions.can_manage'))
|
has_perm(self.request.user, 'motions.can_manage'))
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
from openslides.utils.rest_api import ModelViewSet
|
from openslides.utils.rest_api import ModelViewSet
|
||||||
|
|
||||||
|
from ..utils.auth import has_perm
|
||||||
from .access_permissions import TopicAccessPermissions
|
from .access_permissions import TopicAccessPermissions
|
||||||
from .models import Topic
|
from .models import Topic
|
||||||
|
|
||||||
@ -21,5 +22,5 @@ class TopicViewSet(ModelViewSet):
|
|||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
else:
|
else:
|
||||||
result = self.request.user.has_perm('agenda.can_manage')
|
result = has_perm(self.request.user, 'agenda.can_manage')
|
||||||
return result
|
return result
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
|
from django.contrib.auth.models import AnonymousUser
|
||||||
|
|
||||||
from ..utils.access_permissions import BaseAccessPermissions
|
from ..utils.access_permissions import BaseAccessPermissions
|
||||||
from ..utils.auth import DjangoAnonymousUser, anonymous_is_enabled, has_perm
|
from ..utils.auth import anonymous_is_enabled, has_perm
|
||||||
|
|
||||||
|
|
||||||
class UserAccessPermissions(BaseAccessPermissions):
|
class UserAccessPermissions(BaseAccessPermissions):
|
||||||
@ -42,7 +44,9 @@ class UserAccessPermissions(BaseAccessPermissions):
|
|||||||
case = MANY_DATA
|
case = MANY_DATA
|
||||||
else:
|
else:
|
||||||
case = LITTLE_DATA
|
case = LITTLE_DATA
|
||||||
elif user.pk == full_data.get('id'):
|
elif user is not None and user.id == full_data.get('id'):
|
||||||
|
# An authenticated user without the permission to see users tries
|
||||||
|
# to see himself.
|
||||||
case = LITTLE_DATA
|
case = LITTLE_DATA
|
||||||
else:
|
else:
|
||||||
case = NO_DATA
|
case = NO_DATA
|
||||||
@ -92,10 +96,7 @@ class GroupAccessPermissions(BaseAccessPermissions):
|
|||||||
"""
|
"""
|
||||||
# Every authenticated user can retrieve groups. Anonymous users can do
|
# Every authenticated user can retrieve groups. Anonymous users can do
|
||||||
# so if they are enabled.
|
# so if they are enabled.
|
||||||
# Our AnonymousUser is a subclass of the DjangoAnonymousUser. Normaly, a
|
return not isinstance(user, AnonymousUser) or anonymous_is_enabled()
|
||||||
# DjangoAnonymousUser means, that AnonymousUser is disabled. But this is
|
|
||||||
# no garanty. send_data uses the AnonymousUser in any case.
|
|
||||||
return not isinstance(user, DjangoAnonymousUser) or anonymous_is_enabled()
|
|
||||||
|
|
||||||
def get_serializer_class(self, user=None):
|
def get_serializer_class(self, user=None):
|
||||||
"""
|
"""
|
||||||
|
@ -216,6 +216,12 @@ class User(RESTModelMixin, PermissionsMixin, AbstractBaseUser):
|
|||||||
self.structure_level,
|
self.structure_level,
|
||||||
self.about_me))
|
self.about_me))
|
||||||
|
|
||||||
|
def has_perm(self, perm):
|
||||||
|
"""
|
||||||
|
This method is closed. Do not use it but use openslides.utils.auth.has_perm.
|
||||||
|
"""
|
||||||
|
raise RuntimeError('Do not use user.has_perm() but use openslides.utils.auth.has_perm')
|
||||||
|
|
||||||
|
|
||||||
class GroupManager(GroupManager):
|
class GroupManager(GroupManager):
|
||||||
"""
|
"""
|
||||||
|
@ -5,7 +5,7 @@ from django.utils.encoding import force_text
|
|||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
from ..core.config import config
|
from ..core.config import config
|
||||||
from ..utils.auth import anonymous_is_enabled
|
from ..utils.auth import anonymous_is_enabled, has_perm
|
||||||
from ..utils.collection import CollectionElement
|
from ..utils.collection import CollectionElement
|
||||||
from ..utils.rest_api import (
|
from ..utils.rest_api import (
|
||||||
ModelViewSet,
|
ModelViewSet,
|
||||||
@ -40,11 +40,11 @@ class UserViewSet(ModelViewSet):
|
|||||||
if self.action in ('list', 'retrieve'):
|
if self.action in ('list', 'retrieve'):
|
||||||
result = self.get_access_permissions().check_permissions(self.request.user)
|
result = self.get_access_permissions().check_permissions(self.request.user)
|
||||||
elif self.action in ('metadata', 'update', 'partial_update'):
|
elif self.action in ('metadata', 'update', 'partial_update'):
|
||||||
result = self.request.user.has_perm('users.can_see_name')
|
result = has_perm(self.request.user, 'users.can_see_name')
|
||||||
elif self.action in ('create', 'destroy', 'reset_password'):
|
elif self.action in ('create', 'destroy', 'reset_password'):
|
||||||
result = (self.request.user.has_perm('users.can_see_name') and
|
result = (has_perm(self.request.user, 'users.can_see_name') and
|
||||||
self.request.user.has_perm('users.can_see_extra_data') and
|
has_perm(self.request.user, 'users.can_see_extra_data') and
|
||||||
self.request.user.has_perm('users.can_manage'))
|
has_perm(self.request.user, 'users.can_manage'))
|
||||||
else:
|
else:
|
||||||
result = False
|
result = False
|
||||||
return result
|
return result
|
||||||
@ -59,8 +59,8 @@ class UserViewSet(ModelViewSet):
|
|||||||
wants to update himself or is manager.
|
wants to update himself or is manager.
|
||||||
"""
|
"""
|
||||||
# Check manager perms
|
# Check manager perms
|
||||||
if (request.user.has_perm('users.can_see_extra_data') and
|
if (has_perm(request.user, 'users.can_see_extra_data') and
|
||||||
request.user.has_perm('users.can_manage')):
|
has_perm(request.user, 'users.can_manage')):
|
||||||
if request.data.get('is_active') is False and self.get_object() == request.user:
|
if request.data.get('is_active') is False and self.get_object() == request.user:
|
||||||
# A user can not deactivate himself.
|
# A user can not deactivate himself.
|
||||||
raise ValidationError({'detail': _('You can not deactivate yourself.')})
|
raise ValidationError({'detail': _('You can not deactivate yourself.')})
|
||||||
@ -141,9 +141,9 @@ class GroupViewSet(ModelViewSet):
|
|||||||
result = self.request.user.is_authenticated() or anonymous_is_enabled()
|
result = self.request.user.is_authenticated() or anonymous_is_enabled()
|
||||||
elif self.action in ('create', 'partial_update', 'update', 'destroy'):
|
elif self.action in ('create', 'partial_update', 'update', 'destroy'):
|
||||||
# Users with all app permissions can edit groups.
|
# Users with all app permissions can edit groups.
|
||||||
result = (self.request.user.has_perm('users.can_see_name') and
|
result = (has_perm(self.request.user, 'users.can_see_name') and
|
||||||
self.request.user.has_perm('users.can_see_extra_data') and
|
has_perm(self.request.user, 'users.can_see_extra_data') and
|
||||||
self.request.user.has_perm('users.can_manage'))
|
has_perm(self.request.user, 'users.can_manage'))
|
||||||
else:
|
else:
|
||||||
# Deny request in any other case.
|
# Deny request in any other case.
|
||||||
result = False
|
result = False
|
||||||
|
@ -1,150 +1,31 @@
|
|||||||
from django.contrib.auth import get_user as _get_user
|
|
||||||
from django.contrib.auth import get_user_model
|
from django.contrib.auth import get_user_model
|
||||||
from django.contrib.auth.backends import ModelBackend
|
from django.contrib.auth.models import AnonymousUser
|
||||||
from django.contrib.auth.models import AnonymousUser as DjangoAnonymousUser
|
|
||||||
from django.contrib.auth.models import Permission
|
|
||||||
from django.utils.functional import SimpleLazyObject
|
|
||||||
from rest_framework.authentication import BaseAuthentication
|
|
||||||
|
|
||||||
from .collection import CollectionElement
|
from .collection import CollectionElement
|
||||||
|
|
||||||
|
|
||||||
# Registered users
|
|
||||||
|
|
||||||
class CustomizedModelBackend(ModelBackend):
|
|
||||||
"""
|
|
||||||
Customized backend for authentication. Ensures that all users
|
|
||||||
without a group have the permissions of the group 'Default' (pk=1).
|
|
||||||
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 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'):
|
|
||||||
if user_obj.is_superuser:
|
|
||||||
perms = Permission.objects.all()
|
|
||||||
else:
|
|
||||||
if user_obj.groups.all().count() == 0: # user is in no group
|
|
||||||
perms = Permission.objects.filter(group__pk=1) # group 'default' (pk=1)
|
|
||||||
else:
|
|
||||||
user_groups_field = get_user_model()._meta.get_field('groups')
|
|
||||||
user_groups_query = 'group__%s' % user_groups_field.related_query_name()
|
|
||||||
perms = Permission.objects.filter(**{user_groups_query: user_obj})
|
|
||||||
perms = perms.values_list('content_type__app_label', 'codename').order_by()
|
|
||||||
user_obj._group_perm_cache = set("%s.%s" % (ct, name) for ct, name in perms)
|
|
||||||
return user_obj._group_perm_cache
|
|
||||||
|
|
||||||
|
|
||||||
# Anonymous users
|
|
||||||
|
|
||||||
class AnonymousUser(DjangoAnonymousUser):
|
|
||||||
"""
|
|
||||||
Class for anonymous user instances which have the permissions from the
|
|
||||||
group 'Anonymous' (pk=1).
|
|
||||||
"""
|
|
||||||
|
|
||||||
def has_perm(self, perm, obj=None):
|
|
||||||
"""
|
|
||||||
Checks if the user has a specific permission.
|
|
||||||
"""
|
|
||||||
default_group = CollectionElement.from_values('users/group', 1)
|
|
||||||
return perm in default_group.get_full_data()['permissions']
|
|
||||||
|
|
||||||
|
|
||||||
class RESTFrameworkAnonymousAuthentication(BaseAuthentication):
|
|
||||||
"""
|
|
||||||
Authentication class for the Django REST framework.
|
|
||||||
|
|
||||||
Sets the user to the our AnonymousUser but only if
|
|
||||||
anonymous user is enabled in the config.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def authenticate(self, request):
|
|
||||||
if anonymous_is_enabled():
|
|
||||||
return (AnonymousUser(), None)
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
class AuthenticationMiddleware:
|
|
||||||
"""
|
|
||||||
Middleware to get the logged in user in users.
|
|
||||||
|
|
||||||
Uses AnonymousUser instead of Django's anonymous user.
|
|
||||||
"""
|
|
||||||
def process_request(self, request):
|
|
||||||
"""
|
|
||||||
Like django.contrib.auth.middleware.AuthenticationMiddleware, but uses
|
|
||||||
our own get_user function.
|
|
||||||
"""
|
|
||||||
assert hasattr(request, 'session'), (
|
|
||||||
"The authentication middleware requires session middleware "
|
|
||||||
"to be installed. Edit your MIDDLEWARE_CLASSES setting to insert "
|
|
||||||
"'django.contrib.sessions.middleware.SessionMiddleware' before "
|
|
||||||
"'openslides.utils.auth.AuthenticationMiddleware'."
|
|
||||||
)
|
|
||||||
request.user = SimpleLazyObject(lambda: get_user(request))
|
|
||||||
|
|
||||||
|
|
||||||
def get_user(request):
|
|
||||||
"""
|
|
||||||
Gets the user from the request.
|
|
||||||
|
|
||||||
This is a mix of django.contrib.auth.get_user and
|
|
||||||
django.contrib.auth.middleware.get_user which uses our anonymous user.
|
|
||||||
"""
|
|
||||||
try:
|
|
||||||
return_user = request._cached_user
|
|
||||||
except AttributeError:
|
|
||||||
# Get the user. If it is a DjangoAnonymousUser, then use our AnonymousUser
|
|
||||||
return_user = _get_user(request)
|
|
||||||
if anonymous_is_enabled() and isinstance(return_user, DjangoAnonymousUser):
|
|
||||||
return_user = AnonymousUser()
|
|
||||||
request._cached_user = return_user
|
|
||||||
return return_user
|
|
||||||
|
|
||||||
|
|
||||||
def has_perm(user, perm):
|
def has_perm(user, perm):
|
||||||
"""
|
"""
|
||||||
Checks that user has a specific permission.
|
Checks that user has a specific permission.
|
||||||
|
|
||||||
User can be an user object, an user id None (for anonymous) or a
|
User can be a CollectionElement of a user or None.
|
||||||
CollectionElement for a user.
|
|
||||||
"""
|
"""
|
||||||
# First, convert a user id or None to an anonymous user or an CollectionElement
|
group_collection_string = 'users/group' # This is the hard coded collection string for openslides.users.models.Group
|
||||||
if user is None and anonymous_is_enabled():
|
|
||||||
user = AnonymousUser()
|
|
||||||
elif user is None:
|
|
||||||
user = DjangoAnonymousUser()
|
|
||||||
elif isinstance(user, int):
|
|
||||||
user = CollectionElement.from_values('users/user', user)
|
|
||||||
|
|
||||||
if isinstance(user, AnonymousUser):
|
# Convert user to right type
|
||||||
# Our anonymous user has a has_perm-method that works with the cache
|
user = user_to_collection_user(user)
|
||||||
# system. So we can use it here.
|
if user is None and not anonymous_is_enabled():
|
||||||
has_perm = user.has_perm(perm)
|
|
||||||
elif isinstance(user, DjangoAnonymousUser):
|
|
||||||
# The django anonymous user is only used when anonymous user is disabled
|
|
||||||
# So he never has permissions to see anything.
|
|
||||||
has_perm = False
|
has_perm = False
|
||||||
|
elif user is None:
|
||||||
|
# Use the permissions from the default group with id 1.
|
||||||
|
default_group = CollectionElement.from_values(group_collection_string, 1)
|
||||||
|
has_perm = perm in default_group.get_full_data()['permissions']
|
||||||
else:
|
else:
|
||||||
if isinstance(user, get_user_model()):
|
|
||||||
# Converts a user object to a collection element.
|
|
||||||
# from_instance can not be used because the user serializer loads
|
|
||||||
# the group from the db. So each call to from_instance(user) consts
|
|
||||||
# one db query.
|
|
||||||
user = CollectionElement.from_values('users/user', user.id)
|
|
||||||
|
|
||||||
# Get all groups of the user and then see, if one group has the required
|
# Get all groups of the user and then see, if one group has the required
|
||||||
# permission. If the user has no groups, then use group 1.
|
# permission. If the user has no groups, then use group 1.
|
||||||
group_ids = user.get_full_data()['groups_id'] or [1]
|
group_ids = user.get_full_data()['groups_id'] or [1]
|
||||||
for group_id in group_ids:
|
for group_id in group_ids:
|
||||||
group = CollectionElement.from_values('users/group', group_id)
|
group = CollectionElement.from_values(group_collection_string, group_id)
|
||||||
if perm in group.get_full_data()['permissions']:
|
if perm in group.get_full_data()['permissions']:
|
||||||
has_perm = True
|
has_perm = True
|
||||||
break
|
break
|
||||||
@ -154,5 +35,49 @@ def has_perm(user, perm):
|
|||||||
|
|
||||||
|
|
||||||
def anonymous_is_enabled():
|
def anonymous_is_enabled():
|
||||||
from ..core.config import config
|
"""
|
||||||
return config['general_system_enable_anonymous']
|
Returns True if the anonymous user is enabled in the settings.
|
||||||
|
"""
|
||||||
|
return (CollectionElement.from_values('core/config', 'general_system_enable_anonymous')
|
||||||
|
.get_full_data()['value'])
|
||||||
|
|
||||||
|
|
||||||
|
def user_to_collection_user(user):
|
||||||
|
"""
|
||||||
|
Takes an object, that represents a user and converts it to a CollectionElement
|
||||||
|
or to None, if it is an anonymous user.
|
||||||
|
|
||||||
|
User can be
|
||||||
|
* an user object,
|
||||||
|
* a CollectionElement of an user,
|
||||||
|
* an user id or
|
||||||
|
* an anonymous user.
|
||||||
|
|
||||||
|
Raises an TypeError, if the given user object can not be converted.
|
||||||
|
"""
|
||||||
|
User = get_user_model()
|
||||||
|
|
||||||
|
if user is None:
|
||||||
|
# Nothing to do
|
||||||
|
pass
|
||||||
|
elif isinstance(user, CollectionElement) and user.collection_string == User.get_collection_string():
|
||||||
|
# Nothing to do
|
||||||
|
pass
|
||||||
|
elif isinstance(user, CollectionElement):
|
||||||
|
raise TypeError(
|
||||||
|
"Unsupported type for user. Only CollectionElements for users can be"
|
||||||
|
"used. Not {}".format(user.collection_string))
|
||||||
|
elif isinstance(user, int):
|
||||||
|
user = CollectionElement.from_values(User.get_collection_string(), user)
|
||||||
|
elif isinstance(user, AnonymousUser):
|
||||||
|
user = None
|
||||||
|
elif isinstance(user, User):
|
||||||
|
# Converts a user object to a collection element.
|
||||||
|
# from_instance can not be used because the user serializer loads
|
||||||
|
# the group from the db. So each call to from_instance(user) costs
|
||||||
|
# one db query.
|
||||||
|
user = CollectionElement.from_values(User.get_collection_string(), user.id)
|
||||||
|
else:
|
||||||
|
raise TypeError(
|
||||||
|
"Unsupported type for user. User {} has type {}.".format(user, type(user)))
|
||||||
|
return user
|
||||||
|
@ -11,7 +11,7 @@ from django.db import transaction
|
|||||||
|
|
||||||
from ..core.config import config
|
from ..core.config import config
|
||||||
from ..core.models import Projector
|
from ..core.models import Projector
|
||||||
from .auth import AnonymousUser, anonymous_is_enabled
|
from .auth import has_perm, user_to_collection_user
|
||||||
from .cache import websocket_user_cache
|
from .cache import websocket_user_cache
|
||||||
from .collection import Collection, CollectionElement, CollectionElementList
|
from .collection import Collection, CollectionElement, CollectionElementList
|
||||||
|
|
||||||
@ -67,7 +67,8 @@ def ws_add_site(message):
|
|||||||
# Skip apps that do not implement get_startup_elements
|
# Skip apps that do not implement get_startup_elements
|
||||||
continue
|
continue
|
||||||
for collection in get_startup_elements():
|
for collection in get_startup_elements():
|
||||||
output.extend(collection.as_autoupdate_for_user(message.user.id))
|
user = user_to_collection_user(message.user.id)
|
||||||
|
output.extend(collection.as_autoupdate_for_user(user))
|
||||||
|
|
||||||
# Send all data. If there is no data, then only accept the connection
|
# Send all data. If there is no data, then only accept the connection
|
||||||
if output:
|
if output:
|
||||||
@ -91,12 +92,9 @@ def ws_add_projector(message, projector_id):
|
|||||||
Adds the websocket connection to a group specific to the projector with the given id.
|
Adds the websocket connection to a group specific to the projector with the given id.
|
||||||
Also sends all data that are shown on the projector.
|
Also sends all data that are shown on the projector.
|
||||||
"""
|
"""
|
||||||
user = message.user
|
user = message.user.id
|
||||||
# user is the django anonymous user. We have our own.
|
|
||||||
if user.is_anonymous and anonymous_is_enabled():
|
|
||||||
user = AnonymousUser()
|
|
||||||
|
|
||||||
if not user.has_perm('core.can_see_projector'):
|
if not has_perm(user, 'core.can_see_projector'):
|
||||||
send_or_wait(message.reply_channel.send, {'text': 'No permissions to see this projector.'})
|
send_or_wait(message.reply_channel.send, {'text': 'No permissions to see this projector.'})
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
@ -150,7 +148,7 @@ def send_data(message):
|
|||||||
for user_id, channel_names in websocket_user_cache.get_all().items():
|
for user_id, channel_names in websocket_user_cache.get_all().items():
|
||||||
if not user_id:
|
if not user_id:
|
||||||
# Anonymous user
|
# Anonymous user
|
||||||
user = AnonymousUser()
|
user = None
|
||||||
else:
|
else:
|
||||||
user = CollectionElement.from_values('users/user', user_id)
|
user = CollectionElement.from_values('users/user', user_id)
|
||||||
output = collection_elements.as_autoupdate_for_user(user)
|
output = collection_elements.as_autoupdate_for_user(user)
|
||||||
|
@ -29,6 +29,7 @@ from rest_framework.viewsets import GenericViewSet as _GenericViewSet # noqa
|
|||||||
from rest_framework.viewsets import ModelViewSet as _ModelViewSet # noqa
|
from rest_framework.viewsets import ModelViewSet as _ModelViewSet # noqa
|
||||||
from rest_framework.viewsets import ViewSet as _ViewSet # noqa
|
from rest_framework.viewsets import ViewSet as _ViewSet # noqa
|
||||||
|
|
||||||
|
from .auth import user_to_collection_user
|
||||||
from .collection import Collection, CollectionElement
|
from .collection import Collection, CollectionElement
|
||||||
|
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
@ -182,7 +183,8 @@ class ListModelMixin(_ListModelMixin):
|
|||||||
response = super().list(request, *args, **kwargs)
|
response = super().list(request, *args, **kwargs)
|
||||||
else:
|
else:
|
||||||
collection = Collection(collection_string)
|
collection = Collection(collection_string)
|
||||||
response = Response(collection.as_list_for_user(request.user))
|
user = user_to_collection_user(request.user)
|
||||||
|
response = Response(collection.as_list_for_user(user))
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
@ -206,8 +208,9 @@ class RetrieveModelMixin(_RetrieveModelMixin):
|
|||||||
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
|
||||||
collection_element = CollectionElement.from_values(
|
collection_element = CollectionElement.from_values(
|
||||||
collection_string, self.kwargs[lookup_url_kwarg])
|
collection_string, self.kwargs[lookup_url_kwarg])
|
||||||
|
user = user_to_collection_user(request.user)
|
||||||
try:
|
try:
|
||||||
content = collection_element.as_dict_for_user(request.user)
|
content = collection_element.as_dict_for_user(user)
|
||||||
except collection_element.get_model().DoesNotExist:
|
except collection_element.get_model().DoesNotExist:
|
||||||
raise Http404
|
raise Http404
|
||||||
if content is None:
|
if content is None:
|
||||||
|
@ -102,14 +102,10 @@ class TestTagDBQueries(TestCase):
|
|||||||
def test_anonymous(self):
|
def test_anonymous(self):
|
||||||
"""
|
"""
|
||||||
Tests that only the following db queries are done:
|
Tests that only the following db queries are done:
|
||||||
* 2 requests to get the permission for anonymous (config and permissions)
|
* 1 requests to see if anonyomus is enabled
|
||||||
* 2 requests to get the list of all projectors,
|
* 2 requests to get the list of all projectors,
|
||||||
|
|
||||||
* 10 requests for to config
|
|
||||||
|
|
||||||
The last 10 requests are a bug.
|
|
||||||
"""
|
"""
|
||||||
with self.assertNumQueries(14):
|
with self.assertNumQueries(3):
|
||||||
self.client.get(reverse('tag-list'))
|
self.client.get(reverse('tag-list'))
|
||||||
|
|
||||||
|
|
||||||
@ -140,14 +136,10 @@ class TestConfigDBQueries(TestCase):
|
|||||||
def test_anonymous(self):
|
def test_anonymous(self):
|
||||||
"""
|
"""
|
||||||
Tests that only the following db queries are done:
|
Tests that only the following db queries are done:
|
||||||
* 2 requests to get the permission for anonymous (config and permissions),
|
* 1 requests to see if anonymous is enabled
|
||||||
* 1 to get all config value and
|
* 1 to get all config value and
|
||||||
|
|
||||||
* 57 requests to find out if anonymous is enabled.
|
|
||||||
|
|
||||||
TODO: The last 57 requests are a bug.
|
|
||||||
"""
|
"""
|
||||||
with self.assertNumQueries(63):
|
with self.assertNumQueries(2):
|
||||||
self.client.get(reverse('config-list'))
|
self.client.get(reverse('config-list'))
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,18 +78,10 @@ class TestGroupDBQueries(TestCase):
|
|||||||
def test_anonymous(self):
|
def test_anonymous(self):
|
||||||
"""
|
"""
|
||||||
Tests that only the following db queries are done:
|
Tests that only the following db queries are done:
|
||||||
* 2 requests to find out if anonymous is enabled
|
* 1 requests to find out if anonymous is enabled
|
||||||
* 3 request to get the list of all groups and
|
* 3 request to get the list of all groups and
|
||||||
|
|
||||||
* 14 Requests to find out if anonymous is enabled.
|
|
||||||
|
|
||||||
TODO: There should be only one request to find out if anonymous is enabled.
|
|
||||||
The reason for the last 14 requests is the base get_restricted_data()
|
|
||||||
method that is used by the group access_permissions. It calls check_permissions().
|
|
||||||
But this is important for the autoupdate-case and can only be fixt by
|
|
||||||
caching the config object.
|
|
||||||
"""
|
"""
|
||||||
with self.assertNumQueries(19):
|
with self.assertNumQueries(4):
|
||||||
self.client.get(reverse('group-list'))
|
self.client.get(reverse('group-list'))
|
||||||
|
|
||||||
|
|
||||||
|
@ -15,24 +15,32 @@ class ItemViewSetManageSpeaker(TestCase):
|
|||||||
self.view_instance.get_object = get_object_mock = MagicMock()
|
self.view_instance.get_object = get_object_mock = MagicMock()
|
||||||
get_object_mock.return_value = self.mock_item = MagicMock()
|
get_object_mock.return_value = self.mock_item = MagicMock()
|
||||||
|
|
||||||
|
@patch('openslides.agenda.views.has_perm')
|
||||||
@patch('openslides.agenda.views.Speaker')
|
@patch('openslides.agenda.views.Speaker')
|
||||||
def test_add_oneself_as_speaker(self, mock_speaker):
|
def test_add_oneself_as_speaker(self, mock_speaker, mock_has_perm):
|
||||||
self.request.method = 'POST'
|
self.request.method = 'POST'
|
||||||
self.request.user.has_perm.return_value = True
|
self.request.user = 1
|
||||||
|
mock_has_perm.return_value = True
|
||||||
self.request.data = {}
|
self.request.data = {}
|
||||||
self.mock_item.speaker_list_closed = False
|
self.mock_item.speaker_list_closed = False
|
||||||
|
|
||||||
self.view_instance.manage_speaker(self.request)
|
self.view_instance.manage_speaker(self.request)
|
||||||
|
|
||||||
mock_speaker.objects.add.assert_called_with(self.request.user, self.mock_item)
|
mock_speaker.objects.add.assert_called_with(self.request.user, self.mock_item)
|
||||||
|
|
||||||
|
@patch('openslides.agenda.views.has_perm')
|
||||||
@patch('openslides.agenda.views.get_user_model')
|
@patch('openslides.agenda.views.get_user_model')
|
||||||
@patch('openslides.agenda.views.Speaker')
|
@patch('openslides.agenda.views.Speaker')
|
||||||
def test_add_someone_else_as_speaker(self, mock_speaker, mock_get_user_model):
|
def test_add_someone_else_as_speaker(self, mock_speaker, mock_get_user_model, mock_has_perm):
|
||||||
self.request.method = 'POST'
|
self.request.method = 'POST'
|
||||||
self.request.user.has_perm.return_value = True
|
self.request.user = 1
|
||||||
self.request.data = {'user': '2'} # It is assumed that the request user has pk!=2.
|
self.request.data = {'user': '2'} # It is assumed that the request user has pk!=2.
|
||||||
mock_get_user_model.return_value = MockUser = MagicMock()
|
mock_get_user_model.return_value = MockUser = MagicMock()
|
||||||
MockUser.objects.get.return_value = mock_user = MagicMock()
|
MockUser.objects.get.return_value = mock_user = MagicMock()
|
||||||
|
mock_has_perm.return_value = True
|
||||||
|
|
||||||
self.view_instance.manage_speaker(self.request)
|
self.view_instance.manage_speaker(self.request)
|
||||||
|
|
||||||
MockUser.objects.get.assert_called_with(pk=2)
|
MockUser.objects.get.assert_called_with(pk=2)
|
||||||
mock_speaker.objects.add.assert_called_with(mock_user, self.mock_item)
|
mock_speaker.objects.add.assert_called_with(mock_user, self.mock_item)
|
||||||
|
|
||||||
@ -44,12 +52,16 @@ class ItemViewSetManageSpeaker(TestCase):
|
|||||||
mock_queryset = mock_speaker.objects.filter.return_value.exclude.return_value
|
mock_queryset = mock_speaker.objects.filter.return_value.exclude.return_value
|
||||||
mock_queryset.get.return_value.delete.assert_called_with()
|
mock_queryset.get.return_value.delete.assert_called_with()
|
||||||
|
|
||||||
|
@patch('openslides.agenda.views.has_perm')
|
||||||
@patch('openslides.agenda.views.Speaker')
|
@patch('openslides.agenda.views.Speaker')
|
||||||
def test_remove_someone_else(self, mock_speaker):
|
def test_remove_someone_else(self, mock_speaker, mock_has_perm):
|
||||||
self.request.method = 'DELETE'
|
self.request.method = 'DELETE'
|
||||||
self.request.user.has_perm.return_value = True
|
self.request.user = 1
|
||||||
self.request.data = {'speaker': '1'}
|
self.request.data = {'speaker': '1'}
|
||||||
|
mock_has_perm.return_value = True
|
||||||
|
|
||||||
self.view_instance.manage_speaker(self.request)
|
self.view_instance.manage_speaker(self.request)
|
||||||
|
|
||||||
mock_speaker.objects.get.assert_called_with(pk=1)
|
mock_speaker.objects.get.assert_called_with(pk=1)
|
||||||
mock_speaker.objects.get.return_value.delete.assert_called_with()
|
mock_speaker.objects.get.return_value.delete.assert_called_with()
|
||||||
|
|
||||||
|
@ -16,10 +16,14 @@ class MotionViewSetCreate(TestCase):
|
|||||||
self.view_instance.get_serializer = get_serializer_mock = MagicMock()
|
self.view_instance.get_serializer = get_serializer_mock = MagicMock()
|
||||||
get_serializer_mock.return_value = self.mock_serializer = MagicMock()
|
get_serializer_mock.return_value = self.mock_serializer = MagicMock()
|
||||||
|
|
||||||
|
@patch('openslides.motions.views.has_perm')
|
||||||
@patch('openslides.motions.views.config')
|
@patch('openslides.motions.views.config')
|
||||||
def test_simple_create(self, mock_config):
|
def test_simple_create(self, mock_config, mock_has_perm):
|
||||||
self.request.user.has_perm.return_value = True
|
self.request.user = 1
|
||||||
|
mock_has_perm.return_value = True
|
||||||
|
|
||||||
self.view_instance.create(self.request)
|
self.view_instance.create(self.request)
|
||||||
|
|
||||||
self.mock_serializer.save.assert_called_with(request_user=self.request.user)
|
self.mock_serializer.save.assert_called_with(request_user=self.request.user)
|
||||||
|
|
||||||
|
|
||||||
@ -36,11 +40,15 @@ class MotionViewSetUpdate(TestCase):
|
|||||||
self.view_instance.get_serializer = get_serializer_mock = MagicMock()
|
self.view_instance.get_serializer = get_serializer_mock = MagicMock()
|
||||||
get_serializer_mock.return_value = self.mock_serializer = MagicMock()
|
get_serializer_mock.return_value = self.mock_serializer = MagicMock()
|
||||||
|
|
||||||
|
@patch('openslides.motions.views.has_perm')
|
||||||
@patch('openslides.motions.views.config')
|
@patch('openslides.motions.views.config')
|
||||||
def test_simple_update(self, mock_config):
|
def test_simple_update(self, mock_config, mock_has_perm):
|
||||||
self.request.user.has_perm.return_value = True
|
self.request.user = 1
|
||||||
self.request.data.get.return_value = versioning_mock = MagicMock()
|
self.request.data.get.return_value = versioning_mock = MagicMock()
|
||||||
|
mock_has_perm.return_value = True
|
||||||
|
|
||||||
self.view_instance.update(self.request)
|
self.view_instance.update(self.request)
|
||||||
|
|
||||||
self.mock_serializer.save.assert_called_with(disable_versioning=versioning_mock)
|
self.mock_serializer.save.assert_called_with(disable_versioning=versioning_mock)
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,53 +0,0 @@
|
|||||||
from unittest import TestCase, skip
|
|
||||||
from unittest.mock import MagicMock, patch
|
|
||||||
|
|
||||||
from openslides.utils.auth import AnonymousUser, get_user
|
|
||||||
|
|
||||||
|
|
||||||
@skip # I don't know how to patch the config if it is not imported in the global space
|
|
||||||
@patch('openslides.utils.auth.config')
|
|
||||||
@patch('openslides.utils.auth._get_user')
|
|
||||||
class TestGetUser(TestCase):
|
|
||||||
def test_not_in_cache(self, mock_get_user, mock_config):
|
|
||||||
mock_config.__getitem__.return_value = True
|
|
||||||
mock_get_user.return_value = AnonymousUser()
|
|
||||||
request = MagicMock()
|
|
||||||
del request._cached_user
|
|
||||||
|
|
||||||
user = get_user(request)
|
|
||||||
|
|
||||||
mock_get_user.assert_called_once_with(request)
|
|
||||||
self.assertEqual(user, AnonymousUser())
|
|
||||||
self.assertEqual(request._cached_user, AnonymousUser())
|
|
||||||
|
|
||||||
def test_in_cache(self, mock_get_user, mock_config):
|
|
||||||
request = MagicMock()
|
|
||||||
request._cached_user = 'my_user'
|
|
||||||
|
|
||||||
user = get_user(request)
|
|
||||||
|
|
||||||
self.assertFalse(
|
|
||||||
mock_get_user.called,
|
|
||||||
"_get_user should not have been called when the user object is in cache")
|
|
||||||
self.assertEqual(
|
|
||||||
user,
|
|
||||||
'my_user',
|
|
||||||
"The user in cache should be returned")
|
|
||||||
|
|
||||||
def test_disabled_anonymous_user(self, mock_get_user, mock_config):
|
|
||||||
mock_config.__getitem__.return_value = False
|
|
||||||
mock_get_user.return_value = 'django_anonymous_user'
|
|
||||||
request = MagicMock()
|
|
||||||
del request._cached_user
|
|
||||||
|
|
||||||
user = get_user(request)
|
|
||||||
|
|
||||||
mock_get_user.assert_called_once_with(request)
|
|
||||||
self.assertEqual(
|
|
||||||
user,
|
|
||||||
'django_anonymous_user',
|
|
||||||
"The django user should be returned")
|
|
||||||
self.assertEqual(
|
|
||||||
request._cached_user,
|
|
||||||
'django_anonymous_user',
|
|
||||||
"The django user should be cached")
|
|
Loading…
Reference in New Issue
Block a user