Fix assignment access permissions
Also improves unnecessary history-savings of users in the list of speakers
This commit is contained in:
parent
b50cf42543
commit
fafb81daca
@ -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
|
||||
|
||||
|
||||
|
@ -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":
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
|
@ -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]] = {}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user