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

Feat/ Beta support for graphql #330

Merged
merged 19 commits into from
Jan 19, 2021
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
feat(gql): Add authentication support with jwt
ironcadiz committed Dec 30, 2020

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
commit 94dc12040b9f3de9372898dbe8a4422228e8ff03
55 changes: 55 additions & 0 deletions lib/potassium/assets/app/graphql/graphql_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
class GraphqlController < ApplicationController
# If accessing from outside this domain, nullify the session
# This allows for outside API access while preventing CSRF attacks,
# but you'll have to authenticate your user separately
# protect_from_forgery with: :null_session

def execute
variables = prepare_variables(params[:variables])
query = params[:query]
operation_name = params[:operationName]
context = { current_user: get_current_user }
result = GqlTestSchema.execute(query, variables: variables, context: context, operation_name: operation_name)
render json: result
rescue => e
raise e unless Rails.env.development?
handle_error_in_development e
end
Comment on lines +14 to +17
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

creo que esto se parece a una de las cosas que teníamos en potassium antes y que terminamos sacando porque generaba problemas de replicabilidad development/prod y hacía el debugging más oscuro, no sé si es exacto el caso, pero en general tiendo a preferir que estas condiciones sean solo pa casos muy particulares. Porque si los errores pasan de forma distinta en prod que en dev, se vuelve cacho. Aquí está lo que decía.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eso es parte del boiler plate de la gema.
Entiendo que es su forma de solucionar que solo cuando se caiga en development el endpoint de graphql te responda con el backtrace y el error.
Me hace sentido lo que dices de todas maneras, voy a revisar como se comporta sin eso


private

# Handle variables in form data, JSON body, or a blank value
def prepare_variables(variables_param)
case variables_param
when String
if variables_param.present?
JSON.parse(variables_param) || {}
else
{}
end
when Hash
variables_param
when ActionController::Parameters
variables_param.to_unsafe_hash # GraphQL-Ruby will validate name and type of incoming variables.
when nil
{}
else
raise ArgumentError, "Unexpected parameter: #{variables_param}"
end
end

def handle_error_in_development(e)
logger.error e.message
logger.error e.backtrace.join("\n")

render json: { errors: [{ message: e.message, backtrace: e.backtrace }], data: {} }, status: 500
end

def get_current_user
if request.headers['Authorization']
_, token = request.headers['Authorization'].split
decoded_token = JWT.decode token, ENV['HMAC_SECRET'], true, { algorithm: 'HS256' }
User.find(decoded_token.first["id"])
end
end
end
24 changes: 24 additions & 0 deletions lib/potassium/assets/app/graphql/mutations/login_mutation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
require 'jwt'

class Mutations::LoginMutation < Mutations::BaseMutation
null true

# argument :user_id, ID, required: true, loads: Types::UserType
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no caché esto

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

se me pasó jeje

argument :email, String, required: true
argument :password, String, required: true


field :token, String, null: true

def resolve(email:, password:)
user = User.find_by(email: email)
if user&.valid_password?(password)
payload = { id: user.id, email: user.email, exp: (Time.zone.now + 24.hours).to_i }
token = JWT.encode payload, ENV['HMAC_SECRET'], 'HS256'
return { token: token }
end
GraphQL::ExecutionError.new("User or Password invalid")
rescue ActiveRecord::RecordInvalid => e
GraphQL::ExecutionError.new("Invalid input: #{e.record.errors.full_messages.join(', ')}")
end
end
19 changes: 19 additions & 0 deletions lib/potassium/recipes/api.rb
Original file line number Diff line number Diff line change
@@ -46,6 +46,9 @@ def add_power_api

def add_graphql
gather_gem 'graphql'
if get(:authentication)
gather_gem 'jwt'
end
gather_gems(:development) do
gather_gem 'graphql_playground-rails'
end
@@ -72,6 +75,22 @@ def add_graphql
directory '../assets/app/graphql/queries', 'app/graphql/queries'
gsub_file 'app/graphql/mutations/base_mutation.rb', 'RelayClassic', ''
gsub_file 'app/graphql/mutations/base_mutation.rb', ' input_object_class Types::Base::InputObject\n', ''

if get(:authentication)
copy_file(
'../assets/app/graphql/graphql_controller.rb',
'app/controllers/graphql_controller.rb',
force: true
)
copy_file(
'../assets/app/graphql/mutations/login_mutation.rb',
'app/graphql/mutations/login_mutation.rb'
)
inject_into_file('app/graphql/types/mutation_type.rb',
"\n field :login, mutation: Mutations::LoginMutation",
after: 'class MutationType < Types::Base::BaseObject'
)
ironcadiz marked this conversation as resolved.
Show resolved Hide resolved
end
end
end
end