138 lines
4.3 KiB
Python
138 lines
4.3 KiB
Python
|
|
"""Client serializers for the publish core app."""
|
||
|
|
from rest_framework import exceptions, serializers
|
||
|
|
from timezone_field.rest_framework import TimeZoneSerializerField
|
||
|
|
|
||
|
|
from core import models
|
||
|
|
|
||
|
|
|
||
|
|
class ContactSerializer(serializers.ModelSerializer):
|
||
|
|
"""Serialize contacts."""
|
||
|
|
|
||
|
|
class Meta:
|
||
|
|
model = models.Contact
|
||
|
|
fields = [
|
||
|
|
"id",
|
||
|
|
"base",
|
||
|
|
"data",
|
||
|
|
"full_name",
|
||
|
|
"owner",
|
||
|
|
"short_name",
|
||
|
|
]
|
||
|
|
read_only_fields = ["id", "owner"]
|
||
|
|
|
||
|
|
def update(self, instance, validated_data):
|
||
|
|
"""Make "base" field readonly but only for update/patch."""
|
||
|
|
validated_data.pop("base", None)
|
||
|
|
return super().update(instance, validated_data)
|
||
|
|
|
||
|
|
|
||
|
|
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"]
|
||
|
|
|
||
|
|
class TeamAccessSerializer(serializers.ModelSerializer):
|
||
|
|
"""Serialize team accesses."""
|
||
|
|
|
||
|
|
abilities = serializers.SerializerMethodField(read_only=True)
|
||
|
|
|
||
|
|
class Meta:
|
||
|
|
model = models.TeamAccess
|
||
|
|
fields = ["id", "user", "role", "abilities"]
|
||
|
|
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
|
||
|
|
else "You are not allowed to set this role for this team."
|
||
|
|
)
|
||
|
|
raise exceptions.PermissionDenied(message)
|
||
|
|
|
||
|
|
# Create
|
||
|
|
else:
|
||
|
|
try:
|
||
|
|
team_id = self.context["team_id"]
|
||
|
|
except KeyError as exc:
|
||
|
|
raise exceptions.ValidationError(
|
||
|
|
"You must set a team ID in kwargs to create a new team access."
|
||
|
|
) from exc
|
||
|
|
|
||
|
|
if not models.TeamAccess.objects.filter(
|
||
|
|
team=team_id,
|
||
|
|
user=user,
|
||
|
|
role__in=[models.RoleChoices.OWNER, models.RoleChoices.ADMIN],
|
||
|
|
).exists():
|
||
|
|
raise exceptions.PermissionDenied(
|
||
|
|
"You are not allowed to manage accesses for this team."
|
||
|
|
)
|
||
|
|
|
||
|
|
if (
|
||
|
|
role == models.RoleChoices.OWNER
|
||
|
|
and not models.TeamAccess.objects.filter(
|
||
|
|
team=team_id,
|
||
|
|
user=user,
|
||
|
|
role=models.RoleChoices.OWNER,
|
||
|
|
).exists()
|
||
|
|
):
|
||
|
|
raise exceptions.PermissionDenied(
|
||
|
|
"Only owners of a team can assign other users as owners."
|
||
|
|
)
|
||
|
|
|
||
|
|
attrs["team_id"] = self.context["team_id"]
|
||
|
|
return attrs
|
||
|
|
|
||
|
|
|
||
|
|
class TeamSerializer(serializers.ModelSerializer):
|
||
|
|
"""Serialize teams."""
|
||
|
|
|
||
|
|
abilities = serializers.SerializerMethodField(read_only=True)
|
||
|
|
accesses = TeamAccessSerializer(many=True, read_only=True)
|
||
|
|
|
||
|
|
class Meta:
|
||
|
|
model = models.Team
|
||
|
|
fields = ["id", "name", "accesses", "abilities"]
|
||
|
|
read_only_fields = ["id", "accesses", "abilities"]
|
||
|
|
|
||
|
|
def get_abilities(self, team) -> dict:
|
||
|
|
"""Return abilities of the logged-in user on the instance."""
|
||
|
|
request = self.context.get("request")
|
||
|
|
if request:
|
||
|
|
return team.get_abilities(request.user)
|
||
|
|
return {}
|