OpenSlides/openslides/users/access_permissions.py
Oskar Hahn cd34d30866 Remove utils.collections.Collection class and other cleanups
* Activate restricted_data_cache on inmemory cache
* Use ElementCache in rest-api get requests
* Get requests on the restapi return 404 when the user has no permission
* Added async function for has_perm and in_some_groups
* changed Cachable.get_restricted_data to be an ansync function
* rewrote required_user_system
* changed default implementation of access_permission.check_permission to
  check a given permission or check if anonymous is enabled
2018-11-03 20:48:19 +01:00

144 lines
5.1 KiB
Python

from typing import Any, Dict, List, Optional, Set
from ..utils.access_permissions import BaseAccessPermissions, required_user
from ..utils.auth import async_has_perm
from ..utils.collection import (
CollectionElement,
get_model_from_collection_string,
)
class UserAccessPermissions(BaseAccessPermissions):
"""
Access permissions container for User and UserViewSet.
"""
def get_serializer_class(self, user=None):
"""
Returns different serializer classes with respect user's permissions.
"""
from .serializers import UserFullSerializer
return UserFullSerializer
async def get_restricted_data(
self,
full_data: List[Dict[str, Any]],
user: Optional[CollectionElement]) -> List[Dict[str, Any]]:
"""
Returns the restricted serialized data for the instance prepared
for the user. Removes several fields for non admins so that they do
not get the fields they should not get.
"""
from .serializers import USERCANSEESERIALIZER_FIELDS, USERCANSEEEXTRASERIALIZER_FIELDS
def filtered_data(full_data, whitelist):
"""
Returns a new dict like full_data but only with whitelisted keys.
"""
return {key: full_data[key] for key in whitelist}
# We have five sets of data to be sent:
# * full data i. e. all fields (including session_auth_hash),
# * all data i. e. all fields but not session_auth_hash,
# * many data i. e. all fields but not the default password and session_auth_hash,
# * little data i. e. all fields but not the default password, session_auth_hash, comments and active status,
# * no data.
# Prepare field set for users with "all" data, "many" data and with "little" data.
all_data_fields = set(USERCANSEEEXTRASERIALIZER_FIELDS)
all_data_fields.add('groups_id')
all_data_fields.discard('groups')
all_data_fields.add('default_password')
many_data_fields = all_data_fields.copy()
many_data_fields.discard('default_password')
litte_data_fields = set(USERCANSEESERIALIZER_FIELDS)
litte_data_fields.add('groups_id')
litte_data_fields.discard('groups')
# Check user permissions.
if await async_has_perm(user, 'users.can_see_name'):
if await async_has_perm(user, 'users.can_see_extra_data'):
if await async_has_perm(user, 'users.can_manage'):
data = [filtered_data(full, all_data_fields) for full in full_data]
else:
data = [filtered_data(full, many_data_fields) for full in full_data]
else:
data = [filtered_data(full, litte_data_fields) for full in full_data]
else:
# Build a list of users, that can be seen without any permissions (with little fields).
# Everybody can see himself. Also everybody can see every user
# that is required e. g. as speaker, motion submitter or
# assignment candidate.
can_see_collection_strings: Set[str] = set()
for collection_string in required_user.get_collection_strings():
if await async_has_perm(user, get_model_from_collection_string(collection_string).can_see_permission):
can_see_collection_strings.add(collection_string)
user_ids = await required_user.get_required_users(can_see_collection_strings)
# Add oneself.
if user is not None:
user_ids.add(user.id)
# Parse data.
data = [
filtered_data(full, litte_data_fields)
for full
in full_data
if full['id'] in user_ids]
return data
class GroupAccessPermissions(BaseAccessPermissions):
"""
Access permissions container for Groups. Everyone can see them
"""
def get_serializer_class(self, user=None):
"""
Returns serializer class.
"""
from .serializers import GroupSerializer
return GroupSerializer
class PersonalNoteAccessPermissions(BaseAccessPermissions):
"""
Access permissions container for personal notes. Every authenticated user
can handle personal notes.
"""
def get_serializer_class(self, user=None):
"""
Returns serializer class.
"""
from .serializers import PersonalNoteSerializer
return PersonalNoteSerializer
async def get_restricted_data(
self,
full_data: List[Dict[str, Any]],
user: Optional[CollectionElement]) -> List[Dict[str, Any]]:
"""
Returns the restricted serialized data for the instance prepared
for the user. Everybody gets only his own personal notes.
"""
# Parse data.
if user is None:
data: List[Dict[str, Any]] = []
else:
for full in full_data:
if full['user_id'] == user.id:
data = [full]
break
else:
data = []
return data