2024-03-07 19:46:46 +01:00
|
|
|
"""Client serializers for the impress core app."""
|
2024-03-03 08:49:27 +01:00
|
|
|
from django.db.models import Q
|
2024-02-09 19:32:12 +01:00
|
|
|
from django.utils.translation import gettext_lazy as _
|
|
|
|
|
|
2024-01-09 15:30:36 +01:00
|
|
|
from rest_framework import exceptions, serializers
|
|
|
|
|
from timezone_field.rest_framework import TimeZoneSerializerField
|
|
|
|
|
|
|
|
|
|
from core import models
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class UserSerializer(serializers.ModelSerializer):
|
|
|
|
|
"""Serialize users."""
|
|
|
|
|
|
|
|
|
|
timezone = TimeZoneSerializerField(use_pytz=False, required=True)
|
|
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
|
model = models.User
|
|
|
|
|
fields = [
|
|
|
|
|
"id",
|
|
|
|
|
"language",
|
|
|
|
|
"timezone",
|
|
|
|
|
"is_device",
|
|
|
|
|
"is_staff",
|
|
|
|
|
]
|
|
|
|
|
read_only_fields = ["id", "is_device", "is_staff"]
|
|
|
|
|
|
2024-02-09 19:32:12 +01:00
|
|
|
|
|
|
|
|
class TemplateAccessSerializer(serializers.ModelSerializer):
|
|
|
|
|
"""Serialize template accesses."""
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
abilities = serializers.SerializerMethodField(read_only=True)
|
|
|
|
|
|
|
|
|
|
class Meta:
|
2024-02-09 19:32:12 +01:00
|
|
|
model = models.TemplateAccess
|
2024-03-03 08:49:27 +01:00
|
|
|
fields = ["id", "user", "team", "role", "abilities"]
|
2024-01-09 15:30:36 +01:00
|
|
|
read_only_fields = ["id", "abilities"]
|
|
|
|
|
|
|
|
|
|
def update(self, instance, validated_data):
|
|
|
|
|
"""Make "user" field is readonly but only on update."""
|
|
|
|
|
validated_data.pop("user", None)
|
|
|
|
|
return super().update(instance, validated_data)
|
|
|
|
|
|
|
|
|
|
def get_abilities(self, access) -> dict:
|
|
|
|
|
"""Return abilities of the logged-in user on the instance."""
|
|
|
|
|
request = self.context.get("request")
|
|
|
|
|
if request:
|
|
|
|
|
return access.get_abilities(request.user)
|
|
|
|
|
return {}
|
|
|
|
|
|
|
|
|
|
def validate(self, attrs):
|
|
|
|
|
"""
|
|
|
|
|
Check access rights specific to writing (create/update)
|
|
|
|
|
"""
|
|
|
|
|
request = self.context.get("request")
|
|
|
|
|
user = getattr(request, "user", None)
|
|
|
|
|
role = attrs.get("role")
|
|
|
|
|
|
|
|
|
|
# Update
|
|
|
|
|
if self.instance:
|
|
|
|
|
can_set_role_to = self.instance.get_abilities(user)["set_role_to"]
|
|
|
|
|
|
|
|
|
|
if role and role not in can_set_role_to:
|
|
|
|
|
message = (
|
|
|
|
|
f"You are only allowed to set role to {', '.join(can_set_role_to)}"
|
|
|
|
|
if can_set_role_to
|
2024-02-09 19:32:12 +01:00
|
|
|
else "You are not allowed to set this role for this template."
|
2024-01-09 15:30:36 +01:00
|
|
|
)
|
|
|
|
|
raise exceptions.PermissionDenied(message)
|
|
|
|
|
|
|
|
|
|
# Create
|
|
|
|
|
else:
|
2024-03-03 08:49:27 +01:00
|
|
|
teams = user.get_teams()
|
2024-01-09 15:30:36 +01:00
|
|
|
try:
|
2024-02-09 19:32:12 +01:00
|
|
|
template_id = self.context["template_id"]
|
2024-01-09 15:30:36 +01:00
|
|
|
except KeyError as exc:
|
|
|
|
|
raise exceptions.ValidationError(
|
2024-02-09 19:32:12 +01:00
|
|
|
"You must set a template ID in kwargs to create a new template access."
|
2024-01-09 15:30:36 +01:00
|
|
|
) from exc
|
|
|
|
|
|
2024-02-09 19:32:12 +01:00
|
|
|
if not models.TemplateAccess.objects.filter(
|
2024-03-03 08:49:27 +01:00
|
|
|
Q(user=user) | Q(team__in=teams),
|
2024-02-09 19:32:12 +01:00
|
|
|
template=template_id,
|
2024-01-09 15:30:36 +01:00
|
|
|
role__in=[models.RoleChoices.OWNER, models.RoleChoices.ADMIN],
|
|
|
|
|
).exists():
|
|
|
|
|
raise exceptions.PermissionDenied(
|
2024-02-09 19:32:12 +01:00
|
|
|
"You are not allowed to manage accesses for this template."
|
2024-01-09 15:30:36 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
role == models.RoleChoices.OWNER
|
2024-02-09 19:32:12 +01:00
|
|
|
and not models.TemplateAccess.objects.filter(
|
2024-03-03 08:49:27 +01:00
|
|
|
Q(user=user) | Q(team__in=teams),
|
2024-02-09 19:32:12 +01:00
|
|
|
template=template_id,
|
2024-01-09 15:30:36 +01:00
|
|
|
role=models.RoleChoices.OWNER,
|
|
|
|
|
).exists()
|
|
|
|
|
):
|
|
|
|
|
raise exceptions.PermissionDenied(
|
2024-02-09 19:32:12 +01:00
|
|
|
"Only owners of a template can assign other users as owners."
|
2024-01-09 15:30:36 +01:00
|
|
|
)
|
|
|
|
|
|
2024-02-09 19:32:12 +01:00
|
|
|
attrs["template_id"] = self.context["template_id"]
|
2024-01-09 15:30:36 +01:00
|
|
|
return attrs
|
|
|
|
|
|
|
|
|
|
|
2024-02-09 19:32:12 +01:00
|
|
|
class TemplateSerializer(serializers.ModelSerializer):
|
|
|
|
|
"""Serialize templates."""
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
abilities = serializers.SerializerMethodField(read_only=True)
|
2024-02-09 19:32:12 +01:00
|
|
|
accesses = TemplateAccessSerializer(many=True, read_only=True)
|
2024-01-09 15:30:36 +01:00
|
|
|
|
|
|
|
|
class Meta:
|
2024-02-09 19:32:12 +01:00
|
|
|
model = models.Template
|
|
|
|
|
fields = ["id", "title", "accesses", "abilities"]
|
2024-01-09 15:30:36 +01:00
|
|
|
read_only_fields = ["id", "accesses", "abilities"]
|
|
|
|
|
|
2024-02-09 19:32:12 +01:00
|
|
|
def get_abilities(self, template) -> dict:
|
2024-01-09 15:30:36 +01:00
|
|
|
"""Return abilities of the logged-in user on the instance."""
|
|
|
|
|
request = self.context.get("request")
|
|
|
|
|
if request:
|
2024-02-09 19:32:12 +01:00
|
|
|
return template.get_abilities(request.user)
|
2024-01-09 15:30:36 +01:00
|
|
|
return {}
|
2024-02-09 19:32:12 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
# pylint: disable=abstract-method
|
|
|
|
|
class DocumentGenerationSerializer(serializers.Serializer):
|
|
|
|
|
"""Serializer to receive a request to generate a document on a template."""
|
|
|
|
|
|
|
|
|
|
body = serializers.CharField(label=_("Markdown Body"))
|