Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ en:
password_not_required: "This account does not require a password. Sign in using your '%{provider}' account instead."
reset_token_not_found: "No user found for the specified reset token."
reset_token_expired: "Reset password token is no longer valid."
send_instructions: "You will receive an email with instructions on how to reset your password in a few minutes."
sessions:
bad_credentials: "Invalid login credentials. Please try again."
not_confirmed: "A confirmation email was sent to your account at '%{email}'. You must follow the instructions in the email before your account can be activated"
Expand Down
12 changes: 6 additions & 6 deletions lib/graphql_devise/default_operations/mutations.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@
module GraphqlDevise
module DefaultOperations
MUTATIONS = {
login: GraphqlDevise::Mutations::Login,
logout: GraphqlDevise::Mutations::Logout,
sign_up: GraphqlDevise::Mutations::SignUp,
update_password: GraphqlDevise::Mutations::UpdatePassword,
send_password_reset: GraphqlDevise::Mutations::SendPasswordReset,
resend_confirmation: GraphqlDevise::Mutations::ResendConfirmation
login: { klass: GraphqlDevise::Mutations::Login, authenticatable: true },
logout: { klass: GraphqlDevise::Mutations::Logout, authenticatable: true },
sign_up: { klass: GraphqlDevise::Mutations::SignUp, authenticatable: true },
update_password: { klass: GraphqlDevise::Mutations::UpdatePassword, authenticatable: true },
send_password_reset: { klass: GraphqlDevise::Mutations::SendPasswordReset, authenticatable: false },
resend_confirmation: { klass: GraphqlDevise::Mutations::ResendConfirmation, authenticatable: false }
}.freeze
end
end
4 changes: 2 additions & 2 deletions lib/graphql_devise/default_operations/resolvers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
module GraphqlDevise
module DefaultOperations
QUERIES = {
confirm_account: GraphqlDevise::Resolvers::ConfirmAccount,
check_password_token: GraphqlDevise::Resolvers::CheckPasswordToken
confirm_account: { klass: GraphqlDevise::Resolvers::ConfirmAccount },
check_password_token: { klass: GraphqlDevise::Resolvers::CheckPasswordToken }
}.freeze
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,18 @@ def initialize(selected_operations:, custom_keys:, mapping_name:, preparer:)
end

def call
@selected_operations.except(*@custom_keys).each_with_object({}) do |(action, operation), result|
@selected_operations.except(*@custom_keys).each_with_object({}) do |(action, operation_info), result|
mapped_action = "#{@mapping_name}_#{action}"
operation = operation_info[:klass]
options = operation_info.except(:klass)

result[mapped_action.to_sym] = [
OperationPreparers::GqlNameSetter.new(mapped_action),
@preparer,
OperationPreparers::ResourceNameSetter.new(@mapping_name)
].reduce(child_class(operation)) { |prepared_operation, preparer| preparer.call(prepared_operation) }
].reduce(child_class(operation)) do |prepared_operation, preparer|
preparer.call(prepared_operation, **options)
end
end
end

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def initialize(mapping_name)
@mapping_name = mapping_name
end

def call(operation)
def call(operation, **)
operation.graphql_name(graphql_name)

operation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ def initialize(authenticatable_type)
@authenticatable_type = authenticatable_type
end

def call(mutation)
mutation.field(:authenticatable, @authenticatable_type, null: false)
def call(mutation, authenticatable: true)
return mutation unless authenticatable

mutation.field(:authenticatable, @authenticatable_type, null: false)
mutation
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def initialize(authenticatable_type)
@authenticatable_type = authenticatable_type
end

def call(resolver)
def call(resolver, **)
resolver.type(@authenticatable_type, null: false)

resolver
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def initialize(name)
@name = name
end

def call(operation)
def call(operation, **)
operation.instance_variable_set(:@resource_name, @name)

operation
Expand Down
5 changes: 1 addition & 4 deletions lib/graphql_devise/mutations/resend_confirmation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ def resolve(email:, redirect_url:)
template_path: ['graphql_devise/mailer']
)

{
authenticatable: resource,
message: I18n.t('graphql_devise.confirmations.send_instructions', email: email)
}
{ message: I18n.t('graphql_devise.confirmations.send_instructions', email: email) }
else
raise_user_error(I18n.t('graphql_devise.confirmations.user_not_found', email: email))
end
Expand Down
4 changes: 3 additions & 1 deletion lib/graphql_devise/mutations/send_password_reset.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ class SendPasswordReset < Base
argument :email, String, required: true
argument :redirect_url, String, required: true

field :message, String, null: false

def resolve(email:, redirect_url:)
resource = find_resource(:email, get_case_insensitive_field(:email, email))

Expand All @@ -18,7 +20,7 @@ def resolve(email:, redirect_url:)
)

if resource.errors.empty?
{ authenticatable: resource }
{ message: I18n.t('graphql_devise.passwords.send_instructions') }
else
raise_user_error_list(I18n.t('graphql_devise.invalid_resource'), errors: resource.errors.full_messages)
end
Expand Down
16 changes: 2 additions & 14 deletions spec/requests/mutations/resend_confirmation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,6 @@
redirectUrl:"#{redirect}"
) {
message
authenticatable {
id
email
}
}
}
GRAPHQL
Expand All @@ -28,11 +24,7 @@
it 'sends an email to the user with confirmation url and returns a success message' do
expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
expect(json_response[:data][:userResendConfirmation]).to include(
message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.',
authenticatable: {
id: id,
email: email
}
message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
)

email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
Expand All @@ -56,11 +48,7 @@
it 'honors devise configuration for case insensitive fields' do
expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
expect(json_response[:data][:userResendConfirmation]).to include(
message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.',
authenticatable: {
id: id,
email: user.email
}
message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
)
end
end
Expand Down
11 changes: 8 additions & 3 deletions spec/requests/mutations/send_password_reset_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@
email: "#{email}",
redirectUrl: "#{redirect_url}"
) {
authenticatable {
email
}
message
}
}
GRAPHQL
Expand All @@ -25,6 +23,10 @@
it 'sends password reset email' do
expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)

expect(json_response[:data][:userSendPasswordReset]).to include(
message: 'You will receive an email with instructions on how to reset your password in a few minutes.'
)

email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
link = email.css('a').first

Expand All @@ -41,6 +43,9 @@

it 'honors devise configuration for case insensitive fields' do
expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
expect(json_response[:data][:userSendPasswordReset]).to include(
message: 'You will receive an email with instructions on how to reset your password in a few minutes.'
)
end
end

Expand Down
7 changes: 6 additions & 1 deletion spec/services/mount_method/operation_preparer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,15 @@

let(:logout_class) { Class.new(GraphQL::Schema::Resolver) }
let(:mapping) { :user }
let(:selected) { { login: double(:login_default), logout: logout_class } }
let(:preparer) { double(:preparer, call: logout_class) }
let(:custom) { { login: double(:custom_login, graphql_name: nil) } }
let(:additional) { { user_additional: double(:user_additional) } }
let(:selected) do
{
login: { klass: double(:login_default) },
logout:{ klass: logout_class }
}
end

it 'is expected to return all provided operation keys' do
expect(prepared_operations.keys).to contain_exactly(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,25 @@
let(:logout_operation) { double(:sign_up_operation, graphql_name: nil) }
let(:mapping_name) { :user }
let(:preparer) { double(:preparer) }
let(:operations) { { login: login_operation, logout: logout_operation, sign_up: sign_up_operation, confirm: confirm_operation } }
let(:custom_keys) { [:login, :logout] }
let(:operations) do
{
confirm: { klass: confirm_operation, authenticatable: false },
sign_up: { klass: sign_up_operation, authenticatable: true },
login: { klass: login_operation, authenticatable: true },
logout: { klass: logout_operation, authenticatable: true }
}
end

before do
allow(default_preparer).to receive(:child_class).with(confirm_operation).and_return(confirm_operation)
allow(default_preparer).to receive(:child_class).with(sign_up_operation).and_return(sign_up_operation)
allow(default_preparer).to receive(:child_class).with(login_operation).and_return(login_operation)
allow(default_preparer).to receive(:child_class).with(logout_operation).and_return(logout_operation)
allow(preparer).to receive(:call).with(confirm_operation).and_return(confirm_operation)
allow(preparer).to receive(:call).with(sign_up_operation).and_return(sign_up_operation)
allow(preparer).to receive(:call).with(login_operation).and_return(login_operation)
allow(preparer).to receive(:call).with(logout_operation).and_return(logout_operation)
allow(preparer).to receive(:call).with(confirm_operation, authenticatable: false).and_return(confirm_operation)
allow(preparer).to receive(:call).with(sign_up_operation, authenticatable: true).and_return(sign_up_operation)
allow(preparer).to receive(:call).with(login_operation, authenticatable: true).and_return(login_operation)
allow(preparer).to receive(:call).with(logout_operation, authenticatable: true).and_return(logout_operation)
end

it 'returns only those operations with no custom operation provided' do
Expand All @@ -32,8 +39,8 @@
it 'prepares default operations' do
expect(confirm_operation).to receive(:graphql_name).with('UserConfirm')
expect(sign_up_operation).to receive(:graphql_name).with('UserSignUp')
expect(preparer).to receive(:call).with(confirm_operation)
expect(preparer).to receive(:call).with(sign_up_operation)
expect(preparer).to receive(:call).with(confirm_operation, authenticatable: false)
expect(preparer).to receive(:call).with(sign_up_operation, authenticatable: true)

prepared

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,29 @@

RSpec.describe GraphqlDevise::MountMethod::OperationPreparers::MutationFieldSetter do
describe '#call' do
subject(:prepared_operation) { described_class.new(field_type).call(operation) }
subject(:prepared_operation) { described_class.new(field_type).call(operation, authenticatable: authenticatable) }

let(:operation) { double(:operation) }
let(:field_type) { double(:type) }

it 'sets a field for the mutation' do
expect(operation).to receive(:field).with(:authenticatable, field_type, null: false)
context 'when resource is authtenticable' do
let(:authenticatable) { true }

prepared_operation
it 'sets a field for the mutation' do
expect(operation).to receive(:field).with(:authenticatable, field_type, null: false)

prepared_operation
end
end

context 'when resource is *NOT* authtenticable' do
let(:authenticatable) { false }

it 'does *NOT* set a field for the mutation' do
expect(operation).not_to receive(:field)

prepared_operation
end
end
end
end