Search code examples
pythondjangographqlgraphene-django

How to show specific field only to the user profile owner in graphene-django?


I have the following schema in my graphene-django application:

import graphene
from django.contrib.auth import get_user_model
from graphene_django import DjangoObjectType


class UserType(DjangoObjectType):
    class Meta:
        model = get_user_model()
        fields = ("id", "username", "email")


class Query(object):
    user = graphene.Field(UserType, user_id=graphene.Int())

    def resolve_user(self, info, user_id):
        user = get_user_model().objects.get(pk=user_id)
        if info.context.user.id != user_id:
            # If the query didn't access email field -> query is ok
            # If the query tried to access email field -> raise an error
        else:
            # Logged in as the user we're querying -> let the query access all the fields

I want to be able to query the schema in the following way:

# Logged in as user 1 => no errors, because we're allowed to see all fields
query {
  user (userId: 1) {
    id
    username
    email
  }
}

# Not logged in as user 1 => no errors, because not trying to see email
query {
  user (userId: 1) {
    id
    username
  }
}

# Not logged in as user 1 => return error because accessing email
query {
  user (userId: 1) {
    id
    username
    email
  }
}

How can I make it so that only a logged in user can see the email field of their own profile and no one else can see the emails of others?


Solution

  • I ended up just doing it like this, where the actual value of email is returned when querying one's own info, and None is returned for others:

    import graphene
    from django.contrib.auth import get_user_model
    from graphene_django import DjangoObjectType
    
    
    class UserType(DjangoObjectType):
        class Meta:
            model = get_user_model()
            fields = ("id", "username", "email")
    
        def resolve_email(self, info):
            if info.context.user.is_authenticated and self.pk == info.context.user.pk:
                return self.email
            else:
                return None
    
    
    class Query(graphene.ObjectType):
        user = graphene.Field(UserType, user_id=graphene.Int())
    
        def resolve_user(self, info, user_id):
            return get_user_model().objects.get(pk=user_id)