kramer65
kramer65

Reputation: 53853

How to withold specific properties in Django Rest Framework Serializer based on the logged in user?

I've got a Django Rest Framework API in which I only let logged in users POST new items. The ViewSet looks as follows:

class APIAuthGroup(InAuthGroup):
    """
    A permission to only allow WRITE/POST access if and only if a user is logged in,
    and is a member of the SA role inside keycloak.
    """
    allowed_group_names = [settings.KEYCLOAK_SA_WRITE_PERMISSION]

    def has_permission(self, request, view):
        return request.method in SAFE_METHODS \
               or super(APIAuthGroup, self).has_permission(request, view)


class DevicesViewSet(DatapuntViewSetWritable):
    """
    A view that will return the devices and makes it possible to post new ones
    if the user is logged in
    """

    queryset = Device.objects.all().order_by('id')

    serializer_class = DeviceSerializer
    serializer_detail_class = DeviceSerializer

    http_method_names = ['post', 'list', 'get']

    permission_classes = [APIAuthGroup]

And my serializer:

class PersonSerializer(HALSerializer):
    name = serializers.CharField(required=True, allow_blank=False, max_length=255)
    email = serializers.EmailField()
    organisation = serializers.CharField(required=False, allow_blank=True, max_length=250)

    class Meta:
        model = Person
        fields = ('name', 'email', 'organisation')


class DeviceSerializer(HALSerializer):
    long = serializers.SerializerMethodField()
    lat = serializers.SerializerMethodField()
    organisation = serializers.SerializerMethodField()
    owner = PersonSerializer()
    contact = PersonSerializer(required=False)

    class Meta:
        model = Device
        fields = (
            '_links',
            'id',
            'frequency',
            'longitude',
            'latitude',
            'organisation',
            'owner',
            'contact'
        )

    def get_organisation(self, obj):
        if obj.owner:
            return obj.owner.organisation
        return 'Onbekend'

I now only want the owner and the contact to be returned if the user is logged in and if the logged in user email address is equal to the owner.email.

I'm unsure how and where I would be able to do this though. Should I do this in the serializer, or in the viewset? And how?

Upvotes: 1

Views: 56

Answers (1)

neverwalkaloner
neverwalkaloner

Reputation: 47354

You can override serializer's to_representation method:

class DeviceSerializer(HALSerializer):
    long = serializers.SerializerMethodField()
    lat = serializers.SerializerMethodField()
    organisation = serializers.SerializerMethodField()
    owner = PersonSerializer()
    contact = PersonSerializer(required=False)

    class Meta:
        model = Device
        fields = (
            '_links',
            'id',
            'frequency',
            'longitude',
            'latitude',
            'organisation',
            'owner',
            'contact'
        )

    def get_organisation(self, obj):
        if obj.owner:
            return obj.owner.organisation
        return 'Onbekend'

    def to_representation(self, instance):
        data = super().to_representation(instance)
        if obj.owner != self.context["request"].user:
            data.pop("owner")  # remove from response
            data.pop("contact")  # remove from response
        return data 

Note self.context attribute which contains request object. You can find more details about it here.

Upvotes: 1

Related Questions