import typing from rest_framework import serializers from apps.authorization.models import ( Role, Permissions, UserRelations, Page ) from apps.authentication.api.v1.serializers import serializer as auth_serializer from apps.authentication.models import Organization import itertools class PageSerializer(serializers.ModelSerializer): class Meta: model = Page fields = [ 'name', 'code' ] class PermissionSerializer(serializers.ModelSerializer): class Meta: model = Permissions fields = [ 'id', 'name', 'description', 'category', 'page' ] def to_representation(self, instance): representation = super().to_representation(instance) representation['name'] = 'Hello' return representation @classmethod def permissions_structure_output(cls, permissions: list) -> typing.Any: """ set a structure for permissions """ structure = {} for permission in permissions: if permission.page.name not in structure.keys(): structure.update( {f'{permission.page.name}': itertools.chain(*list( permission.page.permission_page.all().values_list('name'))) }) return structure class RoleSerializer(serializers.ModelSerializer): class Meta: model = Role fields = [ 'id', 'role_name', 'description', 'type', 'permissions' ] extra_kwargs = { 'permissions': {'required': False} # permissions not required for some roles } 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 if instance.permissions: # noqa permissions = instance.permissions.all() representation['permissions'] = PermissionSerializer().permissions_structure_output(permissions) return representation class UserRelationSerializer(serializers.ModelSerializer): class Meta: model = UserRelations fields = [ 'id', 'user', 'organization', 'role', 'permissions', ] 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'] = auth_serializer.OrganizationSerializer(instance.organization).data if instance.role: representation['role'] = RoleSerializer(instance.role).data if instance.permissions: # noqa # set permissions by a default structure like: # 'page permission':[element permissions] permissions = instance.permissions.all() representation['permissions'] = PermissionSerializer().permissions_structure_output(permissions) return representation def update(self, instance, validated_data): """ update user relation object """ if validated_data.get('role'): instance.role = Role.objects.get(id=validated_data.get('role', instance.role)) if validated_data.get('organization'): instance.organization = Organization.objects.get( id=validated_data.get('organization', instance.organization) ) instance.save() instance.permissions.clear() instance.permissions.add(*(validated_data.get('permissions', instance.permissions))) return instance