DEV Community

Cover image for Type Field Authorization in GraphQL Rails with Pundit
Sulman Baig
Sulman Baig

Posted on • Originally published at sulmanweb.com

Type Field Authorization in GraphQL Rails with Pundit

GraphQL-rails  has PRO feature of pundit integration which has easy methodology but its a PRO feature and paid.

Still they provide authorized? methods in open-source version but we have to do it manually. You can learn more about field authorization here.

Pundit is a great object oriented authorization for Rails applications. It helps to separate the authorization logic from controllers so that authorization logic can be changed with time according to the current requirements of the system.

Field Authorization

In GraphQL rails, we want some fields to only be shown to some specific users rather than all users. Here we will first authorize the field of type if success then will show the value of the field according to type, otherwise nil.

I assume that pundit gem is installed and initialized in your code along with definitely GraphQL.

Let’s take an example that a user has a post, and only the owner of the post can see the number of views on the post. But as we have one post type in graphql so people other than owner have access to that field. So we will be authorizing the field for the owner of the post only.

# app/policies/post_policy.rb
class PostPolicy < ApplicationPolicy

  # only if user is the owner of the post
  def owner?
    user.present? && record.user == user
  end

  class Scope < Scope
    def resolve
      scope.all
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

Now that we defined the post policy with owner role, we define the post type with number of view field authorization.

# app/graphql/types/post_type.rb
module Types
  class PostType < Types::BaseObject
    field :id, ID, null: false
    # .... remaining fields
    field :number_of_views, Integer, null: true, description: 'number of times user has viewed your post' do
      def authorized?(object, args, context)
        Pundit.policy(context[:current_user], object)&.owner?
      end
    end

    # resolvers
    def number_of_views
      object.views.count
    end
  end
end
Enter fullscreen mode Exit fullscreen mode

authorized? returns true or false. So if authorization fails then nil is shown, otherwise value is shown. So now in future if owner? definition needs to be changed then it can be done easily. Also we can create the same method name of number_of_views in pundit policy to restriction flow completely in pundit policy.


Happy Coding!

Top comments (0)