153 lines
6.3 KiB
Python
153 lines
6.3 KiB
Python
from typing import Iterable, Tuple
|
|
|
|
from django.apps import apps
|
|
from django.contrib.contenttypes.models import ContentType
|
|
from django.db import models
|
|
|
|
from ..core.config import config
|
|
from ..utils.autoupdate import inform_changed_data
|
|
from ..utils.rest_api import ValidationError
|
|
from .models import Item, ListOfSpeakers
|
|
|
|
|
|
def listen_to_related_object_post_save(sender, instance, created, **kwargs):
|
|
"""
|
|
Receiver function to create agenda items. It is connected to the signal
|
|
django.db.models.signals.post_save during app loading.
|
|
|
|
The agenda_item_update_information container may have fields like type,
|
|
parent_id, comment, duration, weight or skip_autoupdate.
|
|
|
|
Do not run caching and autoupdate if the instance has a key
|
|
skip_autoupdate in the agenda_item_update_information container.
|
|
"""
|
|
instance_inform_changed_data = (
|
|
False # evaluates, if the related_object has to be send again.
|
|
)
|
|
# This is the case, if it was newly created and the autoupdate is not skipped with
|
|
# agenda_item_skip_autoupdate or List_of_speakers_skip_autoupdate. If the related_object is
|
|
# related to agenda items and list of speakers, the autoupdate is skipped, if one of the given
|
|
# values is True.
|
|
is_agenda_item_content_object = hasattr(instance, "get_agenda_title_information")
|
|
is_list_of_speakers_content_object = hasattr(
|
|
instance, "get_list_of_speakers_title_information"
|
|
)
|
|
|
|
if is_agenda_item_content_object:
|
|
if created:
|
|
|
|
if instance.get_collection_string() == "topics/topic":
|
|
should_create_item = True
|
|
elif config["agenda_item_creation"] == "always":
|
|
should_create_item = True
|
|
elif config["agenda_item_creation"] == "never":
|
|
should_create_item = False
|
|
else:
|
|
should_create_item = instance.agenda_item_update_information.get(
|
|
"create"
|
|
)
|
|
if should_create_item is None:
|
|
should_create_item = config["agenda_item_creation"] == "default_yes"
|
|
|
|
if should_create_item:
|
|
attrs = {}
|
|
for attr in ("type", "parent_id", "comment", "duration", "weight"):
|
|
if instance.agenda_item_update_information.get(attr):
|
|
attrs[attr] = instance.agenda_item_update_information.get(attr)
|
|
# Validation: The type is validated in the serializers (to be between 1 and 3).
|
|
# If the parent id is given, set the weight to the parent's weight +1 to
|
|
# ensure the right placement in the tree. Also validate the parent_id!
|
|
parent_id = attrs.get("parent_id")
|
|
if parent_id is not None:
|
|
try:
|
|
parent = Item.objects.get(pk=parent_id)
|
|
except Item.DoesNotExist:
|
|
raise ValidationError(
|
|
{
|
|
"detail": "The parent item with id {0} does not exist",
|
|
"args": [parent_id],
|
|
}
|
|
)
|
|
attrs["weight"] = parent.weight + 1
|
|
Item.objects.create(content_object=instance, **attrs)
|
|
|
|
if not instance.agenda_item_skip_autoupdate:
|
|
instance_inform_changed_data = True
|
|
else:
|
|
is_agenda_item_content_object = False
|
|
# important for the check for item and list of speakers together.
|
|
|
|
elif (
|
|
not instance.agenda_item_skip_autoupdate
|
|
and instance.agenda_item is not None
|
|
):
|
|
# If the object has changed, then also the agenda item has to be sent.
|
|
inform_changed_data(instance.agenda_item)
|
|
|
|
if is_list_of_speakers_content_object:
|
|
if created:
|
|
ListOfSpeakers.objects.create(content_object=instance)
|
|
if not instance.list_of_speakers_skip_autoupdate:
|
|
instance_inform_changed_data = True
|
|
|
|
elif not instance.list_of_speakers_skip_autoupdate:
|
|
# If the object has changed, then also the list of speakers has to be sent.
|
|
inform_changed_data(instance.list_of_speakers)
|
|
|
|
# If the related_object is related to the angenda and list of speakers, check, if skip_autoupdate
|
|
# is False for both,
|
|
if created and is_agenda_item_content_object and is_list_of_speakers_content_object:
|
|
instance_inform_changed_data = not (
|
|
instance.agenda_item_skip_autoupdate
|
|
or instance.list_of_speakers_skip_autoupdate
|
|
)
|
|
|
|
if instance_inform_changed_data:
|
|
inform_changed_data(instance)
|
|
|
|
|
|
def listen_to_related_object_post_delete(sender, instance, **kwargs):
|
|
"""
|
|
Receiver function to delete agenda items. It is connected to the signal
|
|
django.db.models.signals.post_delete during app loading.
|
|
"""
|
|
|
|
has_content_object_mapping: Iterable[Tuple[str, models.Model]] = (
|
|
("get_agenda_title_information", Item),
|
|
("get_list_of_speakers_title_information", ListOfSpeakers),
|
|
)
|
|
|
|
for (attr, Model) in has_content_object_mapping:
|
|
if hasattr(instance, attr):
|
|
content_type = ContentType.objects.get_for_model(instance)
|
|
try:
|
|
Model.objects.get(
|
|
object_id=instance.pk, content_type=content_type
|
|
).delete()
|
|
except Model.DoesNotExist:
|
|
# Model does not exist so we do not have to delete it.
|
|
pass
|
|
|
|
|
|
def get_permission_change_data(sender, permissions, **kwargs):
|
|
"""
|
|
Yields all necessary collections if 'agenda.can_see',
|
|
'agenda.can_see_list_of_speakers', 'agenda.can_see_internal_items'
|
|
or 'agenda.can_manage' permissions changes.
|
|
"""
|
|
agenda_app = apps.get_app_config(app_label="agenda")
|
|
for permission in permissions:
|
|
# There could be only one 'agenda.can_see' and then we want to return data.
|
|
if (
|
|
permission.content_type.app_label == agenda_app.label
|
|
and permission.codename
|
|
in (
|
|
"can_see",
|
|
"can_see_list_of_speakers",
|
|
"can_see_internal_items",
|
|
"can_manage",
|
|
)
|
|
):
|
|
yield from agenda_app.get_startup_elements()
|
|
break
|