Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added ResendConfirmation GraphQL method. #35

Merged
merged 16 commits into from
Nov 24, 2019
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
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,9 @@ is `User`.
1. userSignUp
1. userUpdatePassword
1. userSendPasswordReset
1. `userResendConfirmation(email: String!, redirectUrl: String!): UserResendConfirmationPayload`
aarona marked this conversation as resolved.
Show resolved Hide resolved

The `UserResendConfirmationPayload` will return the `authenticable` resource that was sent the confirmation instructions but also has a `message: String!` that can be used to notify a user what to do after the instructions were sent to them and a `success: Boolean!` to indicate success.
#### Queries
1. userConfirmAccount
1. userCheckPasswordToken
Expand Down
32 changes: 32 additions & 0 deletions app/graphql/graphql_devise/mutations/resend_confirmation.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module GraphqlDevise
module Mutations
class ResendConfirmation < Base
argument :email, String, required: true, prepare: ->(email, _) { email.downcase }
argument :redirect_url, String, required: true

field :message, String, null: false
aarona marked this conversation as resolved.
Show resolved Hide resolved

def resolve(email:, redirect_url:)
resource = controller.find_resource(:uid, email)

if resource
yield resource if block_given?

raise_user_error(I18n.t('errors.messages.already_confirmed')) if resource.confirmed?

resource.send_confirmation_instructions({
redirect_url: redirect_url,
template_path: ['graphql_devise/mailer']
})

{
authenticable: resource,
message: I18n.t('graphql_devise.confirmations.send_instructions', email: email)
}
aarona marked this conversation as resolved.
Show resolved Hide resolved
else
raise_user_error(I18n.t('graphql_devise.confirmations.user_not_found', email: email))
end
end
end
end
end
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<p><%= t(:welcome).capitalize + ' ' + @email %>!</p>

<p><%= t '.confirm_link_msg' %> </p>
<p><%= t '.confirm_link_msg' %></p>

<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>
8 changes: 8 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ en:
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"
confirmations:
invalid_token: "Invalid confirmation token. Please try again"
user_not_found: "Unable to find user with email '%{email}'."
aarona marked this conversation as resolved.
Show resolved Hide resolved
send_instructions: "You will receive an email with instructions for how to confirm your email address in a few minutes."
aarona marked this conversation as resolved.
Show resolved Hide resolved
mailer:
confirmation_instructions:
confirm_link_msg: "You can confirm your account email through the link below:"
confirm_account_link: "Confirm my account"
unlock_instructions:
account_lock_msg: "Your account has been locked due to an excessive number of unsuccessful sign in attempts."
errors:
messages:
already_confirmed: "Email was already confirmed, please try signing in"
3 changes: 2 additions & 1 deletion lib/graphql_devise/rails/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ def mount_graphql_devise_for(resource, opts = {})
logout: GraphqlDevise::Mutations::Logout,
sign_up: GraphqlDevise::Mutations::SignUp,
update_password: GraphqlDevise::Mutations::UpdatePassword,
send_password_reset: GraphqlDevise::Mutations::SendPasswordReset
send_password_reset: GraphqlDevise::Mutations::SendPasswordReset,
resend_confirmation: GraphqlDevise::Mutations::ResendConfirmation
}.freeze
default_queries = {
confirm_account: GraphqlDevise::Resolvers::ConfirmAccount,
Expand Down
1 change: 0 additions & 1 deletion spec/dummy/config/locales/devise.en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ en:
unlocked: "Your account has been unlocked successfully. Please sign in to continue."
errors:
messages:
already_confirmed: "was already confirmed, please try signing in"
confirmation_period_expired: "needs to be confirmed within %{period}, please request a new one"
expired: "has expired, please request a new one"
not_found: "not found"
Expand Down
83 changes: 83 additions & 0 deletions spec/requests/mutations/resend_confirmation_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
require 'rails_helper'

RSpec.describe 'Resend confirmation' do
include_context 'with graphql query request'

let(:user) { create(:user, confirmed_at: nil) }
let(:email) { user.email }
let(:id) { user.id }
let(:redirect) { Faker::Internet.url }
let(:query) do
<<-GRAPHQL
mutation {
userResendConfirmation(
email:"#{email}",
redirectUrl:"#{redirect}"
) {
message
authenticable {
id
email
}
}
}
GRAPHQL
end

context 'when params are correct' do
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(
authenticable: {
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)
link = email.css('a').first
confirm_link_msg_text = email.css('p')[1].inner_html
confirm_account_link_text = link.inner_html

expect(confirm_link_msg_text).to eq("You can confirm your account email through the link below:")
expect(confirm_account_link_text).to eq("Confirm my account")

# TODO: Move to feature spec
expect do
get link['href']
user.reload
end.to change(user, :confirmed_at).from(NilClass).to(ActiveSupport::TimeWithZone)
end

context 'when the user has already been confirmed' do
before { user.confirm }

it 'does *NOT* send an email and raises an error' do
expect { post_request }.to not_change(ActionMailer::Base.deliveries, :count)
expect(json_response[:data][:userResendConfirmation]).to be_nil
expect(json_response[:errors]).to contain_exactly(
hash_including(
message: "Email was already confirmed, please try signing in",
extensions: { code: 'USER_ERROR' }
)
)
end
end
end

context "when the email isn't in the system" do
let(:email) { 'nothere@gmail.com' }

it 'does *NOT* send an email and raises an error' do
expect { post_request }.to not_change(ActionMailer::Base.deliveries, :count)
expect(json_response[:data][:userResendConfirmation]).to be_nil
expect(json_response[:errors]).to contain_exactly(
hash_including(
message: "Unable to find user with email '#{email}'.",
extensions: { code: 'USER_ERROR' }
)
)
end
end
end