Merge pull request #2881 from ostcar/has_perm_with_id

Changed the function has_perm to support an user id or None as the fi…
This commit is contained in:
Norman Jäckel 2017-01-24 22:17:12 +01:00 committed by GitHub
commit e0d5f6d92f
9 changed files with 51 additions and 23 deletions

View File

@ -16,6 +16,7 @@ before_install:
install: install:
- pip install --upgrade setuptools - pip install --upgrade setuptools
- pip install --upgrade --requirement requirements.txt - pip install --upgrade --requirement requirements.txt
- pip freeze
- npm install - npm install
- node_modules/.bin/gulp --production - node_modules/.bin/gulp --production
script: script:

View File

@ -99,6 +99,8 @@ Other:
- Support https as websocket protocol (wss). - Support https as websocket protocol (wss).
- Added migration path from 2.0. - Added migration path from 2.0.
- 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.
- Changed has_perm to support an user id or None (for anyonmous) as first argument.
Version 2.0 (2016-04-18) Version 2.0 (2016-04-18)

View File

@ -1,5 +1,5 @@
from ..utils.access_permissions import BaseAccessPermissions from ..utils.access_permissions import BaseAccessPermissions
from ..utils.auth import DjangoAnonymousUser, has_perm from ..utils.auth import DjangoAnonymousUser, anonymous_is_enabled, has_perm
class ProjectorAccessPermissions(BaseAccessPermissions): class ProjectorAccessPermissions(BaseAccessPermissions):
@ -29,11 +29,9 @@ class TagAccessPermissions(BaseAccessPermissions):
""" """
Returns True if the user has read access model instances. Returns True if the user has read access model instances.
""" """
from .config import config
# 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 config['general_system_enable_anonymous'] return not isinstance(user, DjangoAnonymousUser) or anonymous_is_enabled()
def get_serializer_class(self, user=None): def get_serializer_class(self, user=None):
""" """
@ -112,11 +110,9 @@ class ConfigAccessPermissions(BaseAccessPermissions):
""" """
Returns True if the user has read access model instances. Returns True if the user has read access model instances.
""" """
from .config import config
# 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 config['general_system_enable_anonymous'] return not isinstance(user, DjangoAnonymousUser) or anonymous_is_enabled()
def get_full_data(self, instance): def get_full_data(self, instance):
""" """

View File

@ -17,6 +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.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 (
@ -573,7 +574,7 @@ class TagViewSet(ModelViewSet):
elif self.action == 'metadata': elif self.action == 'metadata':
# Every authenticated user can see the metadata. # Every authenticated user can see the metadata.
# 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 config['general_system_enable_anonymous'] 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 = self.request.user.has_perm('core.can_manage_tags')
else: else:
@ -630,7 +631,7 @@ class ConfigViewSet(ViewSet):
# Every authenticated user can see the metadata and list or # Every authenticated user can see the metadata and list or
# retrieve the config. Anonymous users can do so if they are # retrieve the config. Anonymous users can do so if they are
# enabled. # enabled.
result = self.request.user.is_authenticated() or config['general_system_enable_anonymous'] 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 = self.request.user.has_perm('core.can_manage_config')
else: else:

View File

@ -1,5 +1,5 @@
from ..utils.access_permissions import BaseAccessPermissions from ..utils.access_permissions import BaseAccessPermissions
from ..utils.auth import DjangoAnonymousUser, has_perm from ..utils.auth import DjangoAnonymousUser, anonymous_is_enabled, has_perm
class UserAccessPermissions(BaseAccessPermissions): class UserAccessPermissions(BaseAccessPermissions):
@ -90,14 +90,12 @@ class GroupAccessPermissions(BaseAccessPermissions):
""" """
Returns True if the user has read access model instances. Returns True if the user has read access model instances.
""" """
from ..core.config import config
# 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 # Our AnonymousUser is a subclass of the DjangoAnonymousUser. Normaly, a
# DjangoAnonymousUser means, that AnonymousUser is disabled. But this is # DjangoAnonymousUser means, that AnonymousUser is disabled. But this is
# no garanty. send_data uses the AnonymousUser in any case. # no garanty. send_data uses the AnonymousUser in any case.
return not isinstance(user, DjangoAnonymousUser) or config['general_system_enable_anonymous'] return not isinstance(user, DjangoAnonymousUser) or anonymous_is_enabled()
def get_serializer_class(self, user=None): def get_serializer_class(self, user=None):
""" """

View File

@ -5,6 +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.collection import CollectionElement from ..utils.collection import CollectionElement
from ..utils.rest_api import ( from ..utils.rest_api import (
ModelViewSet, ModelViewSet,
@ -137,7 +138,7 @@ class GroupViewSet(ModelViewSet):
elif self.action == 'metadata': elif self.action == 'metadata':
# Every authenticated user can see the metadata. # Every authenticated user can see the metadata.
# 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 config['general_system_enable_anonymous'] 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 = (self.request.user.has_perm('users.can_see_name') and
@ -247,7 +248,7 @@ class WhoAmIView(APIView):
user_data = None user_data = None
return super().get_context_data( return super().get_context_data(
user_id=user_id, user_id=user_id,
guest_enabled=config['general_system_enable_anonymous'], guest_enabled=anonymous_is_enabled(),
user=user_data, user=user_data,
**context) **context)

View File

@ -62,12 +62,11 @@ class RESTFrameworkAnonymousAuthentication(BaseAuthentication):
Authentication class for the Django REST framework. Authentication class for the Django REST framework.
Sets the user to the our AnonymousUser but only if Sets the user to the our AnonymousUser but only if
general_system_enable_anonymous is set to True in the config. anonymous user is enabled in the config.
""" """
def authenticate(self, request): def authenticate(self, request):
from ..core.config import config if anonymous_is_enabled():
if config['general_system_enable_anonymous']:
return (AnonymousUser(), None) return (AnonymousUser(), None)
return None return None
@ -99,13 +98,12 @@ def get_user(request):
This is a mix of django.contrib.auth.get_user and This is a mix of django.contrib.auth.get_user and
django.contrib.auth.middleware.get_user which uses our anonymous user. django.contrib.auth.middleware.get_user which uses our anonymous user.
""" """
from ..core.config import config
try: try:
return_user = request._cached_user return_user = request._cached_user
except AttributeError: except AttributeError:
# Get the user. If it is a DjangoAnonymousUser, then use our AnonymousUser # Get the user. If it is a DjangoAnonymousUser, then use our AnonymousUser
return_user = _get_user(request) return_user = _get_user(request)
if config['general_system_enable_anonymous'] and isinstance(return_user, DjangoAnonymousUser): if anonymous_is_enabled() and isinstance(return_user, DjangoAnonymousUser):
return_user = AnonymousUser() return_user = AnonymousUser()
request._cached_user = return_user request._cached_user = return_user
return return_user return return_user
@ -114,7 +112,18 @@ def get_user(request):
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
CollectionElement for a user.
""" """
# First, convert a user id or None to an anonymous user or an CollectionElement
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): if isinstance(user, AnonymousUser):
# Our anonymous user has a has_perm-method that works with the cache # Our anonymous user has a has_perm-method that works with the cache
# system. So we can use it here. # system. So we can use it here.
@ -142,3 +151,8 @@ def has_perm(user, perm):
else: else:
has_perm = False has_perm = False
return has_perm return has_perm
def anonymous_is_enabled():
from ..core.config import config
return config['general_system_enable_anonymous']

View File

@ -9,7 +9,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 from .auth import AnonymousUser, anonymous_is_enabled
from .cache import websocket_user_cache from .cache import websocket_user_cache
from .collection import Collection, CollectionElement, CollectionElementList from .collection import Collection, CollectionElement, CollectionElementList
@ -40,7 +40,7 @@ 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)) output.extend(collection.as_autoupdate_for_user(message.user.id))
# 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:
@ -66,7 +66,7 @@ def ws_add_projector(message, projector_id):
""" """
user = message.user user = message.user
# user is the django anonymous user. We have our own. # user is the django anonymous user. We have our own.
if user.is_anonymous and config['general_system_enable_anonymous']: if user.is_anonymous and anonymous_is_enabled():
user = AnonymousUser() user = AnonymousUser()
if not user.has_perm('core.can_see_projector'): if not user.has_perm('core.can_see_projector'):

View File

@ -117,6 +117,9 @@ class CollectionElement:
""" """
Returns a dict that can be sent through the autoupdate system for a site Returns a dict that can be sent through the autoupdate system for a site
user. user.
The argument `user` can be anything, that is allowd as argument for
utils.auth.has_perm().
""" """
return self.as_autoupdate( return self.as_autoupdate(
'get_restricted_data', 'get_restricted_data',
@ -133,6 +136,9 @@ class CollectionElement:
def as_dict_for_user(self, user): def as_dict_for_user(self, user):
""" """
Returns a dict with the data for a user. Can be used for the rest api. Returns a dict with the data for a user. Can be used for the rest api.
The argument `user` can be anything, that is allowd as argument for
utils.auth.has_perm().
""" """
return self.get_access_permissions().get_restricted_data( return self.get_access_permissions().get_restricted_data(
self.get_full_data(), self.get_full_data(),
@ -259,6 +265,9 @@ class CollectionElementList(list):
def as_autoupdate_for_user(self, user): def as_autoupdate_for_user(self, user):
""" """
Returns a list of dicts, that can be send though the websocket to a user. Returns a list of dicts, that can be send though the websocket to a user.
The argument `user` can be anything, that is allowd as argument for
utils.auth.has_perm().
""" """
result = [] result = []
for element in self: for element in self:
@ -355,6 +364,9 @@ class Collection:
def as_autoupdate_for_user(self, user): def as_autoupdate_for_user(self, user):
""" """
Returns a list of dicts, that can be send though the websocket to a user. Returns a list of dicts, that can be send though the websocket to a user.
The argument `user` can be anything, that is allowd as argument for
utils.auth.has_perm().
""" """
output = [] output = []
for collection_element in self.element_generator(): for collection_element in self.element_generator():
@ -367,6 +379,9 @@ class Collection:
""" """
Returns a list of dictonaries to send them to a user, for example over Returns a list of dictonaries to send them to a user, for example over
the rest api. the rest api.
The argument `user` can be anything, that is allowd as argument for
utils.auth.has_perm().
""" """
output = [] output = []
for collection_element in self.element_generator(): for collection_element in self.element_generator():