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

Commit 657a86b

Browse files
authored
Merge pull request #30 from GraphQLAcademy/add-authentication
Add authentication
2 parents bc44dff + ec7a337 commit 657a86b

File tree

11 files changed

+117
-15
lines changed

11 files changed

+117
-15
lines changed

app/controllers/graphql_controller.rb

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
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+
end
27+
1128
def ensure_hash(variables)
1229
if variables.blank?
1330
{}

app/models/graph/types/film.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,11 @@ module Types
2828
field :releaseDate, !types.String,
2929
"The ISO 8601 date format of film release at original creator country.", property: :release_date
3030

31-
field :created_at, !types.String, "The ISO 8601 date format of the time that this resource was created."
32-
field :updated_at, !types.String, "The ISO 8601 date format of the time that this resource was edited."
31+
field :createdAt, !types.String,
32+
"The ISO 8601 date format of the time that this resource was created.", property: :created_at
33+
34+
field :updatedAt, !types.String, "The ISO 8601 date format of the time that this resource was edited.",
35+
property: :updated_at
3336
end
3437
end
3538
end

app/models/graph/types/query.rb

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

49+
field :viewer, Graph::Types::User, 'The currently authenticated user (if any)' do
50+
resolve ->(_, _, ctx) {
51+
ctx[:user]
52+
}
53+
end
54+
4955
# Relay
5056
field :node, GraphQL::Relay::Node.field
5157
field :nodes, GraphQL::Relay::Node.plural_field

app/models/graph/types/species.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ module Types
5050
end
5151

5252
field :language, types.String, "The language commonly spoken by this species."
53-
field :homeworld, Planet, "A planet that this species originates from type." do
53+
field :homeworld, Graph::Types::Planet, "A planet that this species originates from type." do
5454
resolve -> (species, _, _) do
5555
Graph::AssociationLoader.for(::Species, :homeworld).load(species)
5656
end

app/models/graph/types/starship.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,11 @@ module Types
5353
field :consumables, types.String, "The maximum length of time that this starship can provide consumables for its entire crew without having to resupply."
5454
connection :pilots, Graph::Types::Person.connection_type
5555

56-
field :created_at, !types.String, "The ISO 8601 date format of the time that this resource was created."
57-
field :updated_at, !types.String, "The ISO 8601 date format of the time that this resource was updated."
56+
field :createdAt, !types.String,
57+
"The ISO 8601 date format of the time that this resource was created.", property: :created_at
58+
59+
field :updatedAt, !types.String,
60+
"The ISO 8601 date format of the time that this resource was updated.", property: :updated_at
5861
end
5962
end
6063
end

app/models/graph/types/user.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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,
10+
"The ISO 8601 date format of the time that this resource was created.", property: :created_at
11+
field :updatedAt, !types.String,
12+
"The ISO 8601 date format of the time that this resource was updated.", property: :updated_at
13+
end
14+
end
15+
end

app/models/graph/types/vehicle.rb

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,11 @@ module Types
3939
field :consumables, types.String, "The maximum length of time that this vehicle can provide consumables for its entire crew without having to resupply."
4040
connection :pilots, Graph::Types::Person.connection_type
4141

42-
field :created_at, !types.String, "The ISO 8601 date format of the time that this resource was created."
43-
field :updated_at, !types.String, "The ISO 8601 date format of the time that this resource was updated."
42+
field :createdAt, !types.String,
43+
"The ISO 8601 date format of the time that this resource was created.", property: :created_at
44+
45+
field :updatedAt, !types.String,
46+
"The ISO 8601 date format of the time that this resource was updated.", property: :updated_at
4447
end
4548
end
4649
end
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class AddUsernameToUsers < ActiveRecord::Migration[5.0]
2+
def change
3+
change_table :users do |t|
4+
t.string :username
5+
end
6+
add_index :users, :username, unique: true
7+
end
8+
end

db/schema.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
#
1111
# It's strongly recommended that you check this file into your version control system.
1212

13-
ActiveRecord::Schema.define(version: 20170212195638) do
13+
ActiveRecord::Schema.define(version: 20170212223839) do
1414

1515
create_table "films", force: :cascade do |t|
1616
t.string "title"
@@ -153,6 +153,8 @@
153153
t.string "password_digest"
154154
t.datetime "created_at", null: false
155155
t.datetime "updated_at", null: false
156+
t.string "username"
157+
t.index ["username"], name: "index_users_on_username", unique: true
156158
end
157159

158160
create_table "vehicles", force: :cascade do |t|

test/controllers/graphql_controller_test.rb

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class GraphQLControllerTest < ActionDispatch::IntegrationTest
5959
"cargoCapacity" => 100000.0,
6060
"consumables" => "2 months",
6161
"costInCredits" => 100000.0,
62-
"created_at" => "2014-12-10 16:59:45 UTC",
62+
"createdAt" => "2014-12-10 16:59:45 UTC",
6363
"crew" => "4",
6464
"hyperdriveRating" => 0.5,
6565
"length" => 34.37,
@@ -75,7 +75,7 @@ class GraphQLControllerTest < ActionDispatch::IntegrationTest
7575
"cargoCapacity" => 10.0,
7676
"consumables" => "none",
7777
"costInCredits" => nil,
78-
"created_at" => "2014-12-15 12:22:12 UTC",
78+
"createdAt" => "2014-12-15 12:22:12 UTC",
7979
"crew" => "2",
8080
"length" => 4.5,
8181
"manufacturer" => "Incom corporation",
@@ -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
@@ -167,7 +211,7 @@ def full_graphql_query
167211
cargoCapacity
168212
consumables
169213
costInCredits
170-
created_at
214+
createdAt
171215
crew
172216
hyperdriveRating
173217
length
@@ -183,7 +227,7 @@ def full_graphql_query
183227
cargoCapacity
184228
consumables
185229
costInCredits
186-
created_at
230+
createdAt
187231
crew
188232
length
189233
manufacturer

0 commit comments

Comments
 (0)