Skip to content

Commit a780a06

Browse files
committed
Support only option when mounting route
1 parent 75a48dd commit a780a06

9 files changed

Lines changed: 178 additions & 3 deletions

File tree

lib/graphql_devise/rails/routes.rb

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ class Mapper
33
def mount_graphql_devise_for(resource, opts = {})
44
custom_operations = opts[:operations] || {}
55
skipped_operations = opts.fetch(:skip, [])
6+
only_operations = opts.fetch(:only, [])
7+
8+
if [skipped_operations, only_operations].all?(&:any?)
9+
raise GraphqlDevise::Error, "Can't specify both `skip` and `only` options when mounting the route."
10+
end
611

712
default_mutations = {
813
login: GraphqlDevise::Mutations::Login,
@@ -20,6 +25,9 @@ def mount_graphql_devise_for(resource, opts = {})
2025
unless skipped_operations.all? { |skipped| supported_operations.include?(skipped) }
2126
raise GraphqlDevise::Error, 'Trying to skip a non supported operation. Check for typos.'
2227
end
28+
unless only_operations.all? { |only| supported_operations.include?(only) }
29+
raise GraphqlDevise::Error, 'One of the `only` operations is not supported. Check for typos.'
30+
end
2331

2432
path = opts.fetch(:at, '/graphql_auth')
2533
mapping_name = resource.underscore.tr('/', '_').to_sym
@@ -34,7 +42,12 @@ def mount_graphql_devise_for(resource, opts = {})
3442
"Types::#{resource}Type".safe_constantize ||
3543
GraphqlDevise::Types::AuthenticableType
3644

37-
default_mutations.except(*skipped_operations).each do |action, mutation|
45+
used_mutations = if only_operations.present?
46+
default_mutations.slice(*only_operations)
47+
else
48+
default_mutations.except(*skipped_operations)
49+
end
50+
used_mutations.each do |action, mutation|
3851
used_mutation = if custom_operations[action].present?
3952
custom_operations[action]
4053
else
@@ -49,7 +62,12 @@ def mount_graphql_devise_for(resource, opts = {})
4962
GraphqlDevise::Types::MutationType.field("#{mapping_name}_#{action}", mutation: used_mutation)
5063
end
5164

52-
default_queries.except(*skipped_operations).each do |action, query|
65+
used_queries = if only_operations.present?
66+
default_queries.slice(*only_operations)
67+
else
68+
default_queries.except(*skipped_operations)
69+
end
70+
used_queries.each do |action, query|
5371
used_query = if custom_operations[action].present?
5472
custom_operations[action]
5573
else

spec/dummy/app/models/guest.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
class Guest < ApplicationRecord
2+
devise :database_authenticatable,
3+
:registerable,
4+
:recoverable,
5+
:validatable,
6+
:confirmable
7+
8+
include GraphqlDevise::Concerns::Model
9+
end

spec/dummy/config/routes.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,11 @@
1111
at: '/api/v1/admin/graphql_auth'
1212
)
1313

14+
mount_graphql_devise_for(
15+
'Guest',
16+
only: [:login, :logout],
17+
at: '/api/v1/guest/graphql_auth'
18+
)
19+
1420
post '/api/v1/graphql', to: 'api/v1/graphql#graphql'
1521
end
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
class CreateGuests < ActiveRecord::Migration[6.0]
2+
def change
3+
create_table :guests do |t|
4+
## Required
5+
t.string :provider, null: false, default: 'email'
6+
t.string :uid, null: false, default: ''
7+
8+
## Database authenticatable
9+
t.string :encrypted_password, null: false, default: ''
10+
11+
## Recoverable
12+
t.string :reset_password_token
13+
t.datetime :reset_password_sent_at
14+
t.boolean :allow_password_change, default: false
15+
16+
## Confirmable
17+
t.string :confirmation_token
18+
t.datetime :confirmed_at
19+
t.datetime :confirmation_sent_at
20+
t.string :unconfirmed_email # Only if using reconfirmable
21+
22+
## User Info
23+
t.string :email
24+
25+
## Tokens
26+
t.text :tokens
27+
28+
t.timestamps
29+
end
30+
31+
add_index :guests, :email, unique: true
32+
add_index :guests, [:uid, :provider], unique: true
33+
add_index :guests, :reset_password_token, unique: true
34+
add_index :guests, :confirmation_token, unique: true
35+
end
36+
end

spec/dummy/db/schema.rb

Lines changed: 22 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: 2019_09_16_012505) do
13+
ActiveRecord::Schema.define(version: 2019_10_13_213045) do
1414

1515
create_table "admins", force: :cascade do |t|
1616
t.string "provider", default: "email", null: false
@@ -33,6 +33,27 @@
3333
t.index ["uid", "provider"], name: "index_admins_on_uid_and_provider", unique: true
3434
end
3535

36+
create_table "guests", force: :cascade do |t|
37+
t.string "provider", default: "email", null: false
38+
t.string "uid", default: "", null: false
39+
t.string "encrypted_password", default: "", null: false
40+
t.string "reset_password_token"
41+
t.datetime "reset_password_sent_at"
42+
t.boolean "allow_password_change", default: false
43+
t.string "confirmation_token"
44+
t.datetime "confirmed_at"
45+
t.datetime "confirmation_sent_at"
46+
t.string "unconfirmed_email"
47+
t.string "email"
48+
t.text "tokens"
49+
t.datetime "created_at", precision: 6, null: false
50+
t.datetime "updated_at", precision: 6, null: false
51+
t.index ["confirmation_token"], name: "index_guests_on_confirmation_token", unique: true
52+
t.index ["email"], name: "index_guests_on_email", unique: true
53+
t.index ["reset_password_token"], name: "index_guests_on_reset_password_token", unique: true
54+
t.index ["uid", "provider"], name: "index_guests_on_uid_and_provider", unique: true
55+
end
56+
3657
create_table "users", force: :cascade do |t|
3758
t.string "provider", default: "email", null: false
3859
t.string "uid", default: "", null: false

spec/factories/guests.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
FactoryBot.define do
2+
factory :guest do
3+
email { Faker::Internet.unique.email }
4+
password { Faker::Internet.password }
5+
6+
trait :confirmed do
7+
confirmed_at { Time.now }
8+
end
9+
end
10+
end

spec/requests/mutations/login_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,28 @@
114114
)
115115
end
116116
end
117+
118+
context 'when using the guest model' do
119+
let(:guest) { create(:guest, :confirmed, password: password) }
120+
let(:query) do
121+
<<-GRAPHQL
122+
mutation {
123+
guestLogin(
124+
email: "#{guest.email}",
125+
password: "#{password}"
126+
) {
127+
authenticable { email }
128+
}
129+
}
130+
GRAPHQL
131+
end
132+
133+
before { post_request }
134+
135+
it 'works alongside the user mount point' do
136+
expect(json_response[:data][:guestLogin]).to include(
137+
authenticable: { email: guest.email }
138+
)
139+
end
140+
end
117141
end

spec/requests/mutations/sign_up_spec.rb

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,4 +103,31 @@
103103
)
104104
end
105105
end
106+
107+
context 'when using the guest model' do
108+
let(:query) do
109+
<<-GRAPHQL
110+
mutation {
111+
guestSignUp(
112+
email: "#{email}"
113+
password: "#{password}"
114+
passwordConfirmation: "#{password}"
115+
confirmSuccessUrl: "#{redirect}"
116+
) {
117+
authenticable {
118+
email
119+
}
120+
}
121+
}
122+
GRAPHQL
123+
end
124+
125+
before { post_request }
126+
127+
it 'skips the sign up mutation' do
128+
expect(json_response[:errors]).to contain_exactly(
129+
hash_including(message: "Field 'guestSignUp' doesn't exist on type 'Mutation'")
130+
)
131+
end
132+
end
106133
end

spec/requests/queries/check_password_token_spec.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,4 +105,28 @@
105105
)
106106
end
107107
end
108+
109+
context 'when using the guest model' do
110+
let(:token) { 'not_important' }
111+
let(:query) do
112+
<<-GRAPHQL
113+
query {
114+
guestCheckPasswordToken(
115+
resetPasswordToken: "#{token}",
116+
redirectUrl: "#{redirect_url}"
117+
) {
118+
email
119+
}
120+
}
121+
GRAPHQL
122+
end
123+
124+
before { post_request }
125+
126+
it 'skips the sign up mutation' do
127+
expect(json_response[:errors]).to contain_exactly(
128+
hash_including(message: "Field 'guestCheckPasswordToken' doesn't exist on type 'Query'")
129+
)
130+
end
131+
end
108132
end

0 commit comments

Comments
 (0)