Fix assignment access permissions

Also improves unnecessary history-savings of users in the list of speakers
This commit is contained in:
FinnStutzenstein 2019-11-05 11:26:43 +01:00
parent b50cf42543
commit fafb81daca
5 changed files with 26 additions and 42 deletions

View File

@ -426,12 +426,12 @@ class SpeakerManager(models.Manager):
list of speakers and that someone is twice on one list (off coming
speakers). Cares also initial sorting of the coming speakers.
"""
if isinstance(user, AnonymousUser):
raise OpenSlidesError("An anonymous user can not be on lists of speakers.")
if self.filter(
user=user, list_of_speakers=list_of_speakers, begin_time=None
).exists():
raise OpenSlidesError(f"{user} is already on the list of speakers.")
if isinstance(user, AnonymousUser):
raise OpenSlidesError("An anonymous user can not be on lists of speakers.")
if config["agenda_present_speakers_only"] and not user.is_present:
raise OpenSlidesError("Only present users can be on the lists of speakers.")
weight = (
@ -443,7 +443,11 @@ class SpeakerManager(models.Manager):
speaker = self.model(
list_of_speakers=list_of_speakers, user=user, weight=weight + 1
)
speaker.save(force_insert=True, skip_autoupdate=skip_autoupdate)
speaker.save(
force_insert=True,
skip_autoupdate=skip_autoupdate,
no_delete_on_restriction=True,
)
return speaker

View File

@ -356,8 +356,7 @@ class ListOfSpeakersViewSet(
# Send new speaker via autoupdate because users without permission
# to see users may not have it but can get it now.
inform_changed_data([user])
# TODO: inform_changed_data(user) should work. But isinstance(user, Iterable) is true...
inform_changed_data(user, disable_history=True)
# Toggle 'marked' for the speaker
elif request.method == "PATCH":

View File

@ -1,11 +1,8 @@
from typing import Any, Dict, List
from ..poll.access_permissions import (
BasePollAccessPermissions,
BaseVoteAccessPermissions,
)
from ..utils.access_permissions import BaseAccessPermissions
from ..utils.auth import async_has_perm
class AssignmentAccessPermissions(BaseAccessPermissions):
@ -15,38 +12,6 @@ class AssignmentAccessPermissions(BaseAccessPermissions):
base_permission = "assignments.can_see"
async def get_restricted_data(
self, full_data: List[Dict[str, Any]], user_id: int
) -> List[Dict[str, Any]]:
"""
Returns the restricted serialized data for the instance prepared
for the user. Removes unpublished polls for non admins so that they
only get a result like the AssignmentShortSerializer would give them.
"""
# Parse data.
if await async_has_perm(
user_id, "assignments.can_see"
) and await async_has_perm(user_id, "assignments.can_manage"):
data = full_data
elif await async_has_perm(user_id, "assignments.can_see"):
# Exclude unpublished poll votes.
data = []
for full in full_data:
full_copy = full.copy()
polls = full_copy["polls"]
for poll in polls:
if not poll["published"]:
for option in poll["options"]:
option["votes"] = [] # clear votes for not published polls
poll[
"has_votes"
] = False # A user should see, if there are votes.
data.append(full_copy)
else:
data = []
return data
class AssignmentPollAccessPermissions(BasePollAccessPermissions):
base_permission = "assignments.can_see"

View File

@ -9,7 +9,7 @@ from mypy_extensions import TypedDict
from .cache import element_cache, get_element_id
from .projector import get_projector_data
from .utils import get_model_from_collection_string
from .utils import get_model_from_collection_string, is_iterable
class AutoupdateElementBase(TypedDict):
@ -150,6 +150,7 @@ def inform_changed_data(
instances: Union[Iterable[Model], Model],
information: List[str] = None,
user_id: Optional[int] = None,
disable_history: bool = False,
no_delete_on_restriction: bool = False,
) -> None:
"""
@ -162,7 +163,7 @@ def inform_changed_data(
"""
if information is None:
information = []
if not isinstance(instances, Iterable):
if not is_iterable(instances):
instances = (instances,)
root_instances = set(instance.get_root_rest_element() for instance in instances)
@ -170,6 +171,7 @@ def inform_changed_data(
AutoupdateElement(
id=root_instance.get_rest_pk(),
collection_string=root_instance.get_collection_string(),
disable_history=disable_history,
information=information,
user_id=user_id,
no_delete_on_restriction=no_delete_on_restriction,

View File

@ -72,6 +72,20 @@ def is_int(obj: Any) -> bool:
return False
def is_iterable(obj: Any) -> bool:
"""
Do not rely on `isinstance(obj, Iterable` with `Iterable` being imperted
from typing. This breaks at proxyobjects, like SimpleLazyObjects from Django.
Instead try to get the iterable from the object. THis fails on non-iterable
proxyobjects.
"""
try:
iter(obj)
return True
except TypeError:
return False
_models_to_collection_string: Dict[str, Type[Model]] = {}