177 lines
5.5 KiB
Python
177 lines
5.5 KiB
Python
import typing
|
|
from collections import defaultdict
|
|
|
|
from django.db.models.query import QuerySet
|
|
from rest_framework import serializers
|
|
|
|
from apps.authentication.api.v1.serializers import serializer as auth_serializer
|
|
from apps.authorization.models import (
|
|
Role,
|
|
Permissions,
|
|
UserRelations,
|
|
Page
|
|
)
|
|
|
|
|
|
class PageSerializer(serializers.ModelSerializer):
|
|
""" Serialize every front-end page """
|
|
|
|
class Meta:
|
|
model = Page
|
|
fields = [
|
|
'id',
|
|
'name',
|
|
'code',
|
|
'is_active'
|
|
]
|
|
|
|
def to_representation(self, instance):
|
|
""" custom output of serializer """
|
|
representation = super().to_representation(instance)
|
|
representation['permissions'] = PermissionSerializer(
|
|
Permissions.objects.filter(page=instance),
|
|
many=True
|
|
).data
|
|
|
|
return representation
|
|
|
|
|
|
class PermissionSerializer(serializers.ModelSerializer):
|
|
""" Serialize permissions """
|
|
|
|
class Meta:
|
|
model = Permissions
|
|
fields = [
|
|
'id',
|
|
'name',
|
|
'description',
|
|
'category',
|
|
'page',
|
|
'is_active',
|
|
'modify_state'
|
|
]
|
|
|
|
def to_representation(self, instance):
|
|
representation = super().to_representation(instance)
|
|
representation['page'] = instance.page.name
|
|
|
|
return representation
|
|
|
|
@classmethod
|
|
def permissions_structure_output(cls, permissions) -> typing.List[dict]:
|
|
""" set a structure for permissions """
|
|
|
|
if isinstance(permissions, QuerySet):
|
|
permissions = permissions.select_related('page')
|
|
|
|
grouped = defaultdict(set)
|
|
modifier_states = defaultdict(set)
|
|
|
|
for permission in permissions:
|
|
if getattr(permission, 'is_active', True):
|
|
page_name = getattr(permission.page, 'name', None)
|
|
if page_name:
|
|
grouped[page_name].add(permission.name)
|
|
modifier_states[page_name].add(permission.modify_state)
|
|
|
|
structure = [
|
|
{
|
|
'page_name': page,
|
|
'page_access': sorted(list(access))
|
|
} for page, access in grouped.items()
|
|
]
|
|
return structure
|
|
|
|
|
|
class RoleSerializer(serializers.ModelSerializer):
|
|
""" Serialize roles of user """
|
|
|
|
class Meta:
|
|
model = Role
|
|
fields = [
|
|
'id',
|
|
'role_name',
|
|
'parent_role',
|
|
'description',
|
|
'type',
|
|
'permissions' # noqa
|
|
]
|
|
extra_kwargs = {
|
|
'permissions': {'required': False} # permissions not required for some roles # noqa
|
|
}
|
|
|
|
def to_representation(self, instance):
|
|
"""
|
|
using @to_representation for many_to_many permissions in response
|
|
"""
|
|
representation = super().to_representation(instance)
|
|
representation['type'] = auth_serializer.OrganizationTypeSerializer(instance.type).data
|
|
representation['permissions'] = PermissionSerializer(instance.permissions, many=True).data
|
|
if instance.parent_role:
|
|
representation['parent_role'] = {'name': instance.parent_role.role_name, 'id': instance.parent_role.id}
|
|
return representation
|
|
|
|
|
|
class UserRelationSerializer(serializers.ModelSerializer):
|
|
""" Serialize relations of user like: organizations, roles, permissions """
|
|
|
|
class Meta:
|
|
model = UserRelations
|
|
fields = [
|
|
'id',
|
|
'user',
|
|
'organization',
|
|
'role',
|
|
'permissions', # noqa
|
|
]
|
|
|
|
extra_kwargs = {
|
|
'organization': {
|
|
'required': False
|
|
},
|
|
'permissions': { # noqa
|
|
'required': False
|
|
},
|
|
'role': {
|
|
'required': False
|
|
}
|
|
}
|
|
|
|
def to_representation(self, instance):
|
|
""" custom output for serializer """
|
|
|
|
representation = super().to_representation(instance)
|
|
if isinstance(instance, UserRelations):
|
|
if instance.user:
|
|
representation['user'] = auth_serializer.UserSerializer(instance.user).data
|
|
if instance.organization:
|
|
representation['organization'] = {"id": instance.organization.id, "name": instance.organization.name}
|
|
if instance.role:
|
|
representation['role'] = {
|
|
"id": instance.role.id, "role_name": instance.role.role_name, 'type': {
|
|
'key': instance.role.type.key
|
|
}
|
|
}
|
|
if instance.permissions: # noqa
|
|
# set permissions by a default structure like:
|
|
# 'page permission':[element permissions]
|
|
permissions = instance.permissions.filter(is_active=True)
|
|
representation['permissions'] = PermissionSerializer.permissions_structure_output(
|
|
list(permissions) + list(instance.role.permissions.all())
|
|
)
|
|
|
|
return representation
|
|
|
|
def update(self, instance, validated_data):
|
|
""" update user relation object """
|
|
|
|
instance.role = validated_data.get('role', instance.role)
|
|
|
|
instance.organization = validated_data.get('organization', instance.organization)
|
|
instance.save()
|
|
|
|
if validated_data.get('permissions'):
|
|
instance.permissions.clear()
|
|
instance.permissions.add(*(validated_data.get('permissions', instance.permissions)))
|
|
return instance
|