150 lines
5.5 KiB
Python
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
|
|
]
|