Skip to content
This repository was archived by the owner on Sep 24, 2019. It is now read-only.

Commit 1383f3a

Browse files
committed
Add authentication to GraphQL controller
1 parent 3c1b4d5 commit 1383f3a

File tree

5 files changed

+90
-1
lines changed

5 files changed

+90
-1
lines changed

app/controllers/graphql_controller.rb

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,32 @@
11
class GraphqlController < ApplicationController
2+
before_action :authenticate
3+
24
def execute
35
query_string = params[:query].to_s
46
variables = ensure_hash(params[:variables])
5-
result = ::Graph::Schema.execute(query_string, variables: variables)
7+
context = {
8+
user: @user
9+
}
10+
11+
result = Graph::Schema.execute(query_string, variables: variables, context: context)
612
render json: result
713
end
814

915
private
1016

17+
def authenticate
18+
@user = authenticate_with_http_basic { |username, password|
19+
user = User.where(username: username).first
20+
21+
return render plain: 'Invalid username', status: :unauthorized unless user
22+
return render plain: 'Invalid password', status: :authorized unless user.authenticate(password)
23+
24+
user
25+
}
26+
27+
@user ||= GuestUser.new
28+
end
29+
1130
def ensure_hash(variables)
1231
if variables.blank?
1332
{}

app/models/graph/types/query.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@ module Types
4646
}
4747
end
4848

49+
field :viewer, Graph::Types::User, 'The currently authenticated user (if any)' do
50+
resolve ->(_, _, ctx) {
51+
case ctx[:user]
52+
when ::User
53+
ctx[:user]
54+
else
55+
nil
56+
end
57+
}
58+
end
59+
4960
# Relay
5061
field :node, GraphQL::Relay::Node.field
5162
field :nodes, GraphQL::Relay::Node.plural_field

app/models/graph/types/user.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
module Graph
2+
module Types
3+
User = GraphQL::ObjectType.define do
4+
name "User"
5+
description "A user that can rate films."
6+
7+
field :name, !types.String
8+
field :username, !types.String
9+
field :createdAt, !types.String, "The ISO 8601 date format of the time that this resource was created."
10+
field :updatedAt, !types.String, "The ISO 8601 date format of the time that this resource was updated."
11+
end
12+
end
13+
end

app/models/guest_user.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
class GuestUser
2+
end

test/controllers/graphql_controller_test.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,50 @@ class GraphQLControllerTest < ActionDispatch::IntegrationTest
109109
assert_equal expected, JSON.parse(response.body)
110110
end
111111

112+
test "#execute allows authentication via basic auth" do
113+
query = """
114+
{
115+
viewer {
116+
username
117+
}
118+
}
119+
"""
120+
121+
expected = {
122+
"data" => {
123+
"viewer" => {
124+
"username" => "xuorig"
125+
}
126+
}
127+
}
128+
129+
post graphql_url, params: { query: query }, headers: {
130+
"Authorization" => ActionController::HttpAuthentication::Basic.encode_credentials("xuorig", "averysecurepassword"),
131+
}
132+
133+
assert_equal expected, JSON.parse(response.body)
134+
end
135+
136+
test "#execute authentication is not required" do
137+
query = """
138+
{
139+
viewer {
140+
username
141+
}
142+
}
143+
"""
144+
145+
expected = {
146+
"data" => {
147+
"viewer" => nil
148+
}
149+
}
150+
151+
post graphql_url, params: { query: query }
152+
153+
assert_equal expected, JSON.parse(response.body)
154+
end
155+
112156
private
113157

114158
def full_graphql_query

0 commit comments

Comments
 (0)