2026-09-07 19:43:48 +03:00

150 lines
5.5 KiB
Python

"""Сериализаторы для ролей и групп."""
from django.contrib.auth.models import Group, Permission
from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers
from employees.models import DepartmentPermission, DepartmentRole
class DepartmentPermissionVerboseSerializer(serializers.Serializer):
id = serializers.IntegerField()
code = serializers.CharField()
name = serializers.CharField()
class GroupPermissionVerboseSerializer(serializers.Serializer):
id = serializers.IntegerField()
codename = serializers.CharField()
name = serializers.CharField()
app = serializers.CharField()
model = serializers.CharField()
class DepartmentRoleSerializer(serializers.ModelSerializer):
scoped_permissions = serializers.PrimaryKeyRelatedField(
queryset=DepartmentPermission.objects.all(), many=True, required=False
)
scoped_permission_codes = serializers.ListField(
child=serializers.CharField(), required=False, write_only=True
)
permissions = serializers.SerializerMethodField(read_only=True)
permissions_verbose = serializers.SerializerMethodField(read_only=True)
active_assignments_count = serializers.SerializerMethodField(read_only=True)
ldap_linked = serializers.SerializerMethodField(read_only=True)
class Meta:
model = DepartmentRole
fields = (
"id",
"department",
"name",
"scoped_permissions",
"scoped_permission_codes",
"permissions",
"permissions_verbose",
"active_assignments_count",
"ldap_linked",
)
read_only_fields = ("id", "active_assignments_count", "ldap_linked")
def _apply_codes_if_present(self, instance: DepartmentRole, validated_data: dict):
codes = validated_data.pop("scoped_permission_codes", None)
if codes is not None:
qs = DepartmentPermission.objects.filter(code__in=codes)
if qs.count() != len(set(codes)):
raise serializers.ValidationError(
{"scoped_permission_codes": "Некоторые коды не существуют"}
)
instance.scoped_permissions.set(list(qs))
def create(self, validated_data):
codes = validated_data.pop("scoped_permission_codes", None)
perms = validated_data.pop("scoped_permissions", None)
role = super().create(validated_data)
if perms is not None:
role.scoped_permissions.set(perms)
if codes is not None:
qs = DepartmentPermission.objects.filter(code__in=codes)
if qs.count() != len(set(codes)):
raise serializers.ValidationError(
{"scoped_permission_codes": "Некоторые коды не существуют"}
)
role.scoped_permissions.set(list(qs))
return role
def update(self, instance, validated_data):
validated_data.pop("department", None)
codes = validated_data.pop("scoped_permission_codes", None)
perms = validated_data.pop("scoped_permissions", None)
role = super().update(instance, validated_data)
if perms is not None:
role.scoped_permissions.set(perms)
if codes is not None:
qs = DepartmentPermission.objects.filter(code__in=codes)
if qs.count() != len(set(codes)):
raise serializers.ValidationError(
{"scoped_permission_codes": "Некоторые коды не существуют"}
)
role.scoped_permissions.set(list(qs))
return role
@extend_schema_field(serializers.ListField(child=serializers.IntegerField()))
def get_permissions(self, obj: DepartmentRole):
return list(obj.scoped_permissions.values_list("id", flat=True))
@extend_schema_field(DepartmentPermissionVerboseSerializer(many=True))
def get_permissions_verbose(self, obj: DepartmentRole):
return [
{"id": p.id, "code": p.code, "name": p.name}
for p in obj.scoped_permissions.order_by("code").all()
]
@extend_schema_field(serializers.IntegerField())
def get_active_assignments_count(self, obj: DepartmentRole):
employee_ids = set(
obj.assignments.filter(is_active=True).values_list("employee_id", flat=True)
)
employee_ids.update(
obj.members.filter(is_active=True).values_list("employee_id", flat=True)
)
return len(employee_ids)
@extend_schema_field(serializers.BooleanField())
def get_ldap_linked(self, obj: DepartmentRole):
return bool((obj.ldap_group_dn or "").strip())
class GroupSerializer(serializers.ModelSerializer):
permissions = serializers.PrimaryKeyRelatedField(
queryset=Permission.objects.all(), many=True, required=False
)
permissions_verbose = serializers.SerializerMethodField(read_only=True)
class Meta:
model = Group
fields = ["id", "name", "permissions", "permissions_verbose"]
@extend_schema_field(GroupPermissionVerboseSerializer(many=True))
def get_permissions_verbose(self, obj):
qs = obj.permissions.select_related("content_type").all()
return [
{
"id": p.id,
"codename": f"{p.content_type.app_label}.{p.codename}",
"name": p.name,
"app": p.content_type.app_label,
"model": p.content_type.model,
}
for p in qs
]