Skip to content

Commit beacc61

Browse files
authored
Use the url where the schema is mounted in emails links (#106)
* Use the url where the schema is mounted in the reset password email link * Add changes for confirmation email
1 parent 766a7d2 commit beacc61

11 files changed

Lines changed: 133 additions & 37 deletions

File tree

app/views/graphql_devise/mailer/confirmation_instructions.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22

33
<p><%= t('.confirm_link_msg') %></p>
44

5-
<p><%= link_to t('.confirm_account_link'), url_for(controller: 'graphql_devise/graphql', action: :auth, **confirmation_query(resource_name: @resource.class.to_s, redirect_url: message['redirect-url'], token: @token)) %></p>
5+
<p><%= link_to t('.confirm_account_link'), url_for(controller: message['controller'], action: message['action'], **confirmation_query(resource_name: @resource.class.to_s, redirect_url: message['redirect-url'], token: @token)) %></p>

app/views/graphql_devise/mailer/reset_password_instructions.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<p><%= t('.request_reset_link_msg') %></p>
44

5-
<p><%= link_to t('.password_change_link'), url_for(controller: 'graphql_devise/graphql', action: :auth, **password_reset_query(token: @token, redirect_url: message['redirect-url'], resource_name: @resource.class.to_s)) %></p>
5+
<p><%= link_to t('.password_change_link'), url_for(controller: message['controller'], action: message['action'], **password_reset_query(token: @token, redirect_url: message['redirect-url'], resource_name: @resource.class.to_s)) %></p>
66

77
<p><%= t('.ignore_mail_msg') %></p>
88
<p><%= t('.no_changes_msg') %></p>

lib/graphql_devise/mutations/resend_confirmation.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ def resolve(email:, redirect_url:)
1919

2020
resource.send_confirmation_instructions(
2121
redirect_url: redirect_url,
22-
template_path: ['graphql_devise/mailer']
22+
template_path: ['graphql_devise/mailer'],
23+
**controller.params.permit('controller', 'action').to_h.symbolize_keys
2324
)
2425

2526
{ message: I18n.t('graphql_devise.confirmations.send_instructions', email: email) }

lib/graphql_devise/mutations/send_password_reset.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ def resolve(email:, redirect_url:)
1616
email: email,
1717
provider: 'email',
1818
redirect_url: redirect_url,
19-
template_path: ['graphql_devise/mailer']
19+
template_path: ['graphql_devise/mailer'],
20+
**controller.params.permit('controller', 'action').to_h.symbolize_keys
2021
)
2122

2223
if resource.errors.empty?

lib/graphql_devise/mutations/sign_up.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ def resolve(confirm_success_url: nil, **attrs)
2727
unless resource.confirmed?
2828
resource.send_confirmation_instructions(
2929
redirect_url: confirm_success_url,
30-
template_path: ['graphql_devise/mailer']
30+
template_path: ['graphql_devise/mailer'],
31+
**controller.params.permit('controller', 'action').to_h.symbolize_keys
3132
)
3233
end
3334

spec/dummy/app/controllers/api/v1/graphql_controller.rb

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@ class GraphqlController < ApplicationController
44
include GraphqlDevise::Concerns::SetUserByToken
55

66
def graphql
7-
render json: DummySchema.execute(params[:query], context: graphql_context(:user))
7+
result = DummySchema.execute(params[:query], execute_params(params))
8+
9+
render json: result unless performed?
810
end
911

1012
def interpreter
11-
render json: InterpreterSchema.execute(params[:query], context: graphql_context(:user))
13+
render json: InterpreterSchema.execute(params[:query], execute_params(params))
1214
end
1315

1416
def failing_resource_name
@@ -17,6 +19,31 @@ def failing_resource_name
1719

1820
private
1921

22+
def execute_params(item)
23+
{
24+
operation_name: item[:operationName],
25+
variables: ensure_hash(item[:variables]),
26+
context: graphql_context(:user)
27+
}
28+
end
29+
30+
def ensure_hash(ambiguous_param)
31+
case ambiguous_param
32+
when String
33+
if ambiguous_param.present?
34+
ensure_hash(JSON.parse(ambiguous_param))
35+
else
36+
{}
37+
end
38+
when Hash, ActionController::Parameters
39+
ambiguous_param
40+
when nil
41+
{}
42+
else
43+
raise ArgumentError, "Unexpected parameter: #{ambiguous_param}"
44+
end
45+
end
46+
2047
def verify_authenticity_token
2148
end
2249
end

spec/dummy/app/graphql/dummy_schema.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,16 @@ class DummySchema < GraphQL::Schema
33
query: Types::QueryType,
44
mutation: Types::MutationType,
55
resource_loaders: [
6-
GraphqlDevise::ResourceLoader.new('User', only: [:login, :confirm_account]),
6+
GraphqlDevise::ResourceLoader.new(
7+
'User',
8+
only: [
9+
:login,
10+
:confirm_account,
11+
:send_password_reset,
12+
:resend_confirmation,
13+
:check_password_token
14+
]
15+
),
716
GraphqlDevise::ResourceLoader.new('Guest', only: [:logout])
817
]
918
)

spec/dummy/config/routes.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
at: '/api/v1/user_customer/graphql_auth'
2828
)
2929

30+
get '/api/v1/graphql', to: 'api/v1/graphql#graphql'
3031
post '/api/v1/graphql', to: 'api/v1/graphql#graphql'
3132
post '/api/v1/interpreter', to: 'api/v1/graphql#interpreter'
3233
post '/api/v1/failing', to: 'api/v1/graphql#failing_resource_name'

spec/requests/mutations/resend_confirmation_spec.rb

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,25 +21,52 @@
2121
end
2222

2323
context 'when params are correct' do
24-
it 'sends an email to the user with confirmation url and returns a success message' do
25-
expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
26-
expect(json_response[:data][:userResendConfirmation]).to include(
27-
message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
28-
)
24+
context 'when using the gem schema' do
25+
it 'sends an email to the user with confirmation url and returns a success message' do
26+
expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
27+
expect(json_response[:data][:userResendConfirmation]).to include(
28+
message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
29+
)
30+
31+
email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
32+
link = email.css('a').first
33+
confirm_link_msg_text = email.css('p')[1].inner_html
34+
confirm_account_link_text = link.inner_html
35+
36+
expect(link['href']).to include('/api/v1/graphql_auth?')
37+
expect(confirm_link_msg_text).to eq('You can confirm your account email through the link below:')
38+
expect(confirm_account_link_text).to eq('Confirm my account')
39+
40+
expect do
41+
get link['href']
42+
user.reload
43+
end.to change(user, :confirmed_at).from(NilClass).to(ActiveSupport::TimeWithZone)
44+
end
45+
end
46+
47+
context 'when using a custom schema' do
48+
let(:custom_path) { '/api/v1/graphql' }
49+
50+
it 'sends an email to the user with confirmation url and returns a success message' do
51+
expect { post_request(custom_path) }.to change(ActionMailer::Base.deliveries, :count).by(1)
52+
expect(json_response[:data][:userResendConfirmation]).to include(
53+
message: 'You will receive an email with instructions for how to confirm your email address in a few minutes.'
54+
)
2955

30-
email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
31-
link = email.css('a').first
32-
confirm_link_msg_text = email.css('p')[1].inner_html
33-
confirm_account_link_text = link.inner_html
56+
email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
57+
link = email.css('a').first
58+
confirm_link_msg_text = email.css('p')[1].inner_html
59+
confirm_account_link_text = link.inner_html
3460

35-
expect(confirm_link_msg_text).to eq('You can confirm your account email through the link below:')
36-
expect(confirm_account_link_text).to eq('Confirm my account')
61+
expect(link['href']).to include("#{custom_path}?")
62+
expect(confirm_link_msg_text).to eq('You can confirm your account email through the link below:')
63+
expect(confirm_account_link_text).to eq('Confirm my account')
3764

38-
# TODO: Move to feature spec
39-
expect do
40-
get link['href']
41-
user.reload
42-
end.to change(user, :confirmed_at).from(NilClass).to(ActiveSupport::TimeWithZone)
65+
expect do
66+
get link['href']
67+
user.reload
68+
end.to change(user, :confirmed_at).from(NilClass).to(ActiveSupport::TimeWithZone)
69+
end
4370
end
4471

4572
context 'when email address uses different casing' do

spec/requests/mutations/send_password_reset_spec.rb

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -20,21 +20,44 @@
2020
end
2121

2222
context 'when params are correct' do
23-
it 'sends password reset email' do
24-
expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
23+
context 'when using the gem schema' do
24+
it 'sends password reset email' do
25+
expect { post_request }.to change(ActionMailer::Base.deliveries, :count).by(1)
2526

26-
expect(json_response[:data][:userSendPasswordReset]).to include(
27-
message: 'You will receive an email with instructions on how to reset your password in a few minutes.'
28-
)
27+
expect(json_response[:data][:userSendPasswordReset]).to include(
28+
message: 'You will receive an email with instructions on how to reset your password in a few minutes.'
29+
)
30+
31+
email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
32+
link = email.css('a').first
33+
expect(link['href']).to include('/api/v1/graphql_auth?')
34+
35+
expect do
36+
get link['href']
37+
user.reload
38+
end.to change(user, :allow_password_change).from(false).to(true)
39+
end
40+
end
41+
42+
context 'when using a custom schema' do
43+
let(:custom_path) { '/api/v1/graphql' }
44+
45+
it 'sends password reset email' do
46+
expect { post_request(custom_path) }.to change(ActionMailer::Base.deliveries, :count).by(1)
47+
48+
expect(json_response[:data][:userSendPasswordReset]).to include(
49+
message: 'You will receive an email with instructions on how to reset your password in a few minutes.'
50+
)
2951

30-
email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
31-
link = email.css('a').first
52+
email = Nokogiri::HTML(ActionMailer::Base.deliveries.last.body.encoded)
53+
link = email.css('a').first
54+
expect(link['href']).to include("#{custom_path}?")
3255

33-
# TODO: Move to feature spec
34-
expect do
35-
get link['href']
36-
user.reload
37-
end.to change(user, :allow_password_change).from(false).to(true)
56+
expect do
57+
get link['href']
58+
user.reload
59+
end.to change(user, :allow_password_change).from(false).to(true)
60+
end
3861
end
3962
end
4063

0 commit comments

Comments
 (0)