Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
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
6 changes: 5 additions & 1 deletion app/graphql/graphql_devise/mutations/sign_up.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class SignUp < Base
argument :confirm_success_url, String, required: false

def resolve(confirm_success_url: nil, **attrs)
resource = resource_class.new(provider: provider, **attrs)
resource = build_resource(attrs.merge(provider: provider))
raise_user_error(I18n.t('graphql_devise.resource_build_failed')) if resource.blank?

redirect_url = confirm_success_url || DeviseTokenAuth.default_confirm_success_url
Expand Down Expand Up @@ -45,6 +45,10 @@ def resolve(confirm_success_url: nil, **attrs)

private

def build_resource(attrs)
resource_class.new(attrs)
end

def provider
:email
end
Expand Down
18 changes: 13 additions & 5 deletions lib/graphql_devise/rails/routes.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
module ActionDispatch::Routing
class Mapper
def mount_graphql_devise_for(resource, opts = {})
custom_operations = opts[:operations] || {}
skipped_operations = opts.fetch(:skip, [])
only_operations = opts.fetch(:only, [])
custom_operations = opts.fetch(:operations, {})
skipped_operations = opts.fetch(:skip, [])
only_operations = opts.fetch(:only, [])
additional_mutations = opts.fetch(:additional_mutations, {})
additional_queries = opts.fetch(:additional_queries, {})

if [skipped_operations, only_operations].all?(&:any?)
raise GraphqlDevise::Error, "Can't specify both `skip` and `only` options when mounting the route."
Expand Down Expand Up @@ -62,8 +64,11 @@ def mount_graphql_devise_for(resource, opts = {})

GraphqlDevise::Types::MutationType.field("#{mapping_name}_#{action}", mutation: used_mutation)
end
additional_mutations.each do |action, mutation|
GraphqlDevise::Types::MutationType.field(action, mutation: mutation)
end

if used_mutations.present? &&
if (used_mutations.present? || additional_mutations.present?) &&
(Gem::Version.new(GraphQL::VERSION) <= Gem::Version.new('1.10.0') || GraphqlDevise::Schema.mutation.nil?)
GraphqlDevise::Schema.mutation(GraphqlDevise::Types::MutationType)
end
Expand All @@ -87,8 +92,11 @@ def mount_graphql_devise_for(resource, opts = {})

GraphqlDevise::Types::QueryType.field("#{mapping_name}_#{action}", resolver: used_query)
end
additional_queries.each do |action, resolver|
GraphqlDevise::Types::QueryType.field(action, resolver: resolver)
end

if used_queries.blank? && GraphqlDevise::Types::QueryType.fields.blank?
if (used_queries.blank? || additional_queries.present?) && GraphqlDevise::Types::QueryType.fields.blank?
GraphqlDevise::Types::QueryType.field(:dummy, resolver: GraphqlDevise::Resolvers::Dummy)
end

Expand Down
23 changes: 23 additions & 0 deletions spec/dummy/app/graphql/mutations/register_confirmed_user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
module Mutations
class RegisterConfirmedUser < GraphqlDevise::Mutations::Base
argument :email, String, required: true
argument :name, String, required: true
argument :password, String, required: true
argument :password_confirmation, String, required: true

field :user, Types::UserType, null: true

def resolve(**attrs)
user = User.new(attrs.merge(confirmed_at: Time.zone.now))

if user.save
{ user: user }
else
raise_user_error_list(
'Custom registration failed',
errors: user.errors.full_messages
)
end
end
end
end
11 changes: 11 additions & 0 deletions spec/dummy/app/graphql/resolvers/public_user.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module Resolvers
class PublicUser < GraphQL::Schema::Resolver
type Types::UserType, null: false

argument :id, Int, required: true

def resolve(id:)
User.find(id)
end
end
end
4 changes: 4 additions & 0 deletions spec/dummy/config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
mount_graphql_devise_for 'User', at: '/api/v1/graphql_auth', operations: {
login: Mutations::Login,
sign_up: Mutations::SignUp
}, additional_mutations: {
register_confirmed_user: Mutations::RegisterConfirmedUser
}, additional_queries: {
public_user: Resolvers::PublicUser
}

mount_graphql_devise_for(
Expand Down
65 changes: 65 additions & 0 deletions spec/requests/mutations/additional_mutations_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
require 'rails_helper'

RSpec.describe 'Additional Mutations' do
include_context 'with graphql query request'

let(:name) { Faker::Name.name }
let(:password) { Faker::Internet.password }
let(:password_confirmation) { password }
let(:email) { Faker::Internet.email }
let(:redirect) { Faker::Internet.url }

context 'when using the user model' do
let(:query) do
<<-GRAPHQL
mutation {
registerConfirmedUser(
email: "#{email}",
name: "#{name}",
password: "#{password}",
passwordConfirmation: "#{password_confirmation}"
) {
user {
email
name
}
}
}
GRAPHQL
end

context 'when params are correct' do
it 'creates a new resource that is already confirmed' do
expect { post_request }.to(
change(User, :count).by(1)
.and(not_change(ActionMailer::Base.deliveries, :count))
)

user = User.last

expect(user).to be_confirmed
expect(json_response[:data][:registerConfirmedUser]).to include(
user: {
email: email,
name: name
}
)
end
end

context 'when params are incorrect' do
let(:password_confirmation) { 'not the same' }

it 'returns descriptive errors' do
expect { post_request }.to not_change(User, :count)

expect(json_response[:errors]).to contain_exactly(
hash_including(
message: 'Custom registration failed',
extensions: { code: 'USER_ERROR', detailed_errors: ["Password confirmation doesn't match Password"] }
)
)
end
end
end
end
31 changes: 31 additions & 0 deletions spec/requests/mutations/additional_queries_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
require 'rails_helper'

RSpec.describe 'Additional Queries' do
include_context 'with graphql query request'

let(:public_user) { create(:user, :confirmed) }

context 'when using the user model' do
let(:query) do
<<-GRAPHQL
query {
publicUser(
id: #{public_user.id}
) {
email
name
}
}
GRAPHQL
end

before { post_request }

it 'fetches a user by ID' do
expect(json_response[:data][:publicUser]).to include(
email: public_user.email,
name: public_user.name
)
end
end
end