dd4754d045
Before this commit, there where two different locks when updating the restricted data cache. A future lock, what is faster but only works in the same thread. The other lock is in redis, it is not so fast, but also works in many threads. The future lock was buggy, because on a second call of update_restricted_data the same future was reused. So on the second run, the future was already done. I don't see any way to delete. The last client would have to delete it, but there is no way to find out which client the last one is.
192 lines
4.8 KiB
Python
192 lines
4.8 KiB
Python
from typing import Any
|
|
|
|
from .models import (
|
|
ChatMessage,
|
|
ConfigStore,
|
|
Countdown,
|
|
History,
|
|
ProjectionDefault,
|
|
Projector,
|
|
ProjectorMessage,
|
|
Tag,
|
|
)
|
|
from ..utils.projector import projector_slides
|
|
from ..utils.rest_api import Field, IntegerField, ModelSerializer, ValidationError
|
|
from ..utils.validate import validate_html
|
|
|
|
|
|
class JSONSerializerField(Field):
|
|
"""
|
|
Serializer for projector's and config JSONField.
|
|
"""
|
|
|
|
def to_internal_value(self, data):
|
|
"""
|
|
Returns the value. It is encoded from the Django JSONField.
|
|
"""
|
|
return data
|
|
|
|
def to_representation(self, value):
|
|
"""
|
|
Returns the value. It is decoded from the Django JSONField.
|
|
"""
|
|
return value
|
|
|
|
|
|
class ProjectionDefaultSerializer(ModelSerializer):
|
|
"""
|
|
Serializer for core.models.ProjectionDefault objects.
|
|
"""
|
|
|
|
class Meta:
|
|
model = ProjectionDefault
|
|
fields = ("id", "name", "display_name", "projector")
|
|
|
|
|
|
def elements_validator(value: Any) -> None:
|
|
"""
|
|
Checks the format of the elements field.
|
|
"""
|
|
if not isinstance(value, list):
|
|
raise ValidationError({"detail": "Data must be a list."})
|
|
for element in value:
|
|
if not isinstance(element, dict):
|
|
raise ValidationError({"detail": "Data must be a dictionary."})
|
|
if element.get("name") is None:
|
|
raise ValidationError(
|
|
{"detail": "Every dictionary must have a key 'name'."}
|
|
)
|
|
if element["name"] not in projector_slides:
|
|
raise ValidationError(
|
|
{"detail": f"Unknown projector element {element['name']},"}
|
|
)
|
|
|
|
|
|
def elements_array_validator(value: Any) -> None:
|
|
"""
|
|
Validates the value of the element field of the projector model.
|
|
"""
|
|
if not isinstance(value, list):
|
|
raise ValidationError({"detail": "Data must be a list."})
|
|
for element in value:
|
|
elements_validator(element)
|
|
|
|
|
|
class ProjectorSerializer(ModelSerializer):
|
|
"""
|
|
Serializer for core.models.Projector objects.
|
|
"""
|
|
|
|
elements = JSONSerializerField(validators=[elements_validator])
|
|
elements_preview = JSONSerializerField(validators=[elements_validator])
|
|
elements_history = JSONSerializerField(validators=[elements_array_validator])
|
|
|
|
projectiondefaults = ProjectionDefaultSerializer(many=True, read_only=True)
|
|
width = IntegerField(min_value=800, max_value=3840, required=False)
|
|
height = IntegerField(min_value=340, max_value=2880, required=False)
|
|
|
|
class Meta:
|
|
model = Projector
|
|
fields = (
|
|
"id",
|
|
"elements",
|
|
"elements_preview",
|
|
"elements_history",
|
|
"scale",
|
|
"scroll",
|
|
"name",
|
|
"width",
|
|
"height",
|
|
"reference_projector",
|
|
"projectiondefaults",
|
|
"background_color",
|
|
"header_background_color",
|
|
"header_font_color",
|
|
"header_h1_color",
|
|
"show_header_footer",
|
|
"show_title",
|
|
"show_logo",
|
|
)
|
|
read_only_fields = ("scale", "scroll")
|
|
|
|
|
|
class TagSerializer(ModelSerializer):
|
|
"""
|
|
Serializer for core.models.Tag objects.
|
|
"""
|
|
|
|
class Meta:
|
|
model = Tag
|
|
fields = ("id", "name")
|
|
|
|
|
|
class ConfigSerializer(ModelSerializer):
|
|
"""
|
|
Serializer for core.models.Tag objects.
|
|
"""
|
|
|
|
value = JSONSerializerField()
|
|
|
|
class Meta:
|
|
model = ConfigStore
|
|
fields = ("id", "key", "value")
|
|
|
|
|
|
class ChatMessageSerializer(ModelSerializer):
|
|
"""
|
|
Serializer for core.models.ChatMessage objects.
|
|
"""
|
|
|
|
class Meta:
|
|
model = ChatMessage
|
|
fields = ("id", "message", "timestamp", "user")
|
|
read_only_fields = ("user",)
|
|
|
|
|
|
class ProjectorMessageSerializer(ModelSerializer):
|
|
"""
|
|
Serializer for core.models.ProjectorMessage objects.
|
|
"""
|
|
|
|
class Meta:
|
|
model = ProjectorMessage
|
|
fields = ("id", "message")
|
|
|
|
def validate(self, data):
|
|
if "message" in data:
|
|
data["message"] = validate_html(data["message"])
|
|
return data
|
|
|
|
|
|
class CountdownSerializer(ModelSerializer):
|
|
"""
|
|
Serializer for core.models.Countdown objects.
|
|
"""
|
|
|
|
class Meta:
|
|
model = Countdown
|
|
fields = (
|
|
"id",
|
|
"title",
|
|
"description",
|
|
"default_time",
|
|
"countdown_time",
|
|
"running",
|
|
)
|
|
unique_together = ("title",)
|
|
|
|
|
|
class HistorySerializer(ModelSerializer):
|
|
"""
|
|
Serializer for core.models.Countdown objects.
|
|
|
|
Does not contain full data of history object.
|
|
"""
|
|
|
|
information = JSONSerializerField()
|
|
|
|
class Meta:
|
|
model = History
|
|
fields = ("id", "element_id", "now", "information", "restricted", "user")
|
|
read_only_fields = ("now",)
|