Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to pass context in query? #55

Open
egonm12 opened this issue Dec 5, 2018 · 14 comments
Open

How to pass context in query? #55

egonm12 opened this issue Dec 5, 2018 · 14 comments
Labels

Comments

@egonm12
Copy link

egonm12 commented Dec 5, 2018

How can I pass the current_user context in a query? In the execute method I see: query_params[:context] = @options if @options.

I got this shared_context:

# frozen_string_literal: true

require "active_record"
require "graphlient"

RSpec.shared_context "Graphql Client", shared_context: :metadata do
  include Rack::Test::Methods

  let(:client) do
    Graphlient::Client.new("http://api-example.com/graphql") do |client|
      client.http do |h|
        h.connection do |c|
          c.use Faraday::Adapter::Rack, Rails.application
        end
      end
    end

  end
end

Since I am using query authorization I can't simply query something like:

query = <<-GRAPHQL
        mutation {
          createInvite(
            team_id: 1
            email: "[email protected]"
          )
        }
      GRAPHQL

client.query(query)

Because I need the context[:current_user]

@yuki24
Copy link
Collaborator

yuki24 commented Dec 5, 2018

There doesn't seem to be a way to override context for each query, but I think it's just adding a new argument to the execute method and deep-merge with the @options. PRs are welcome!

@egonm12
Copy link
Author

egonm12 commented Dec 5, 2018

@yuki24 So I thought I had a solution but when executing a query it comes through the execute method in my GraphQL controller, which sets my current_user again, which will become nil. Only solution I think that works is directly calling my App schema instead of using this gem. Any ideas?

@yuki24
Copy link
Collaborator

yuki24 commented Dec 5, 2018

I'm not sure I understand. Would you mind posting a code snippet?

@egonm12
Copy link
Author

egonm12 commented Dec 5, 2018

  def execute(query, **kwargs) <--------------- Changed
      query_params = {}

      @options = @options.deep_merge(kwargs[:context]) if kwargs[:context] <--------------- Changed
      query_params[:context] = @options if @options
      query_params[:variables] = kwargs[:variables] if kwargs[:variables] <--------------- Changed

      query = client.parse(query) if query.is_a?(String)
      rc = client.query(query, query_params)
      raise Graphlient::Errors::GraphQLError, rc if rc.errors.any?
      # see https://github.com/github/graphql-client/pull/132
      # see https://github.com/exAspArk/graphql-errors/issues/2
      raise Graphlient::Errors::ExecutionError, rc if rc.data&.errors && rc.data.errors.any?
      rc
    rescue GraphQL::Client::Error => e
      raise Graphlient::Errors::ClientError, e.message
    end

    def query(query_or_variables = nil, variables = nil, context = nil, &block)  <--------------- Changed
      if block_given?
        execute(parse(&block), query_or_variables)
      else
        execute(query_or_variables, variables: variables, context: context) <--------------- Changed
      end
    end

And assume I called: client.query(query, variables, context)
Than query_params will give back:

{:context=>
  {:current_user=>
    #<User id: 2, name: "Rheba", created_at: "2018-12-05 12:51:54", updated_at: "2018-12-05 12:51:54">},
 :variables=>{:id=>1}}

So at this point everything works but when calling client.query(query, query_params) it will come across the execute method in my controller. In that controller it says: context: { current_user: current_user } and because of that it will become nil because that current_user is set through authorization header.

@egonm12
Copy link
Author

egonm12 commented Dec 5, 2018

Ok I found an other solution, instead of doing it like above I can do this in my spec:

token = AuthToken.new.token(user)
client.options[:headers] = { "Authorization": "Bearer #{token}" }

This will create the current_user context for me.

@dblock
Copy link
Collaborator

dblock commented Dec 5, 2018

Is there something we still want in Graphlient for this?

@dblock dblock added the question label Dec 5, 2018
@yuki24
Copy link
Collaborator

yuki24 commented Dec 5, 2018

@dblock we may want to add the ability to override context on query:

query = <<-GRAPHQL
  query($ids: [Int]) {
    ...
  }
GRAPHQL
variables = {ids: [42]}

client.query(query, variables, context: ...) # Right now this isn't possible

@dblock
Copy link
Collaborator

dblock commented Dec 5, 2018

Makes sense. Maybe someone can try a PR? Wink wink @egonm12 ;)

@egonm12
Copy link
Author

egonm12 commented Dec 5, 2018

@dblock I will look into it. My first try in #55 (comment) didn't work properly as you can see.

@ashkan18
Copy link
Owner

ashkan18 commented Jan 9, 2019

thanks for describing the issue @egonm12 , I wonder what is the use case for updating context per query. When you create the client you can set JWT header with passing hash of headers:

Graphlient::Client.new('http://localhost:4000/api/graphql', headers: headers)

in your case are you trying to update JWT for one specific query or you want to have the token as a parameter merged into query variables?

@dblock
Copy link
Collaborator

dblock commented Apr 24, 2019

Looks like #58 is related.

@forsbergplustwo
Copy link

@ashkan18 We have a use case for needing to be able to switch context per query, maybe it helps explain.

On the Shopify GraphQL API, each user/store has it's own unique endpoint (url) and bearer token.
The Schema is the same for all users/stores, so if we could re-assign the client context at runtime in our apps, we don't need to create a new client each time. This helps a lot with performance & memory utilisation.

Hope that makes sense :)

@dblock
Copy link
Collaborator

dblock commented Aug 16, 2019

That seems reasonable to me, want to try to PR this?

@forsbergplustwo
Copy link

I wish I could, but I don't have the skills :(

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants