Created
March 24, 2020 18:08
-
-
Save kylefox/59e0b8e72a40859ca0ca6ac3b3a65235 to your computer and use it in GitHub Desktop.
Rails controller concern for automatically signing in Devise users after they confirm their email address.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
shared_context 'sign in after confirmation' do |resource_name:| | |
before do | |
@request.env['devise.mapping'] = Devise.mappings[resource_name] | |
end | |
shared_examples 'failed confirmation' do |error:| | |
it { is_expected.to have_http_status :ok } | |
it { is_expected.to render_template 'devise/confirmations/new' } | |
it "has errors on @#{resource_name}" do | |
subject | |
expect(assigns[resource_name].errors.full_messages).to eq([error]) | |
end | |
end | |
shared_examples 'successful confirmation' do |action:| | |
it "#{action}s the #{resource_name}" do | |
message = action == :confirm ? :confirmation_required? : :pending_reconfirmation? | |
expect { subject }.to(change { resource.reload.send(message) }.from(true).to(false)) | |
end | |
it 'sets the flash' do | |
subject | |
expect(flash[:notice]).to eq I18n.t('devise.confirmations.confirmed') | |
end | |
end | |
shared_examples 'prompted to sign in' do | |
it { is_expected.to redirect_to send("new_#{resource_name}_session_path") } | |
it 'does not sign in the user' do | |
expect { subject }.to_not(change { @controller.send("current_#{resource_name}") }.from(nil)) | |
end | |
end | |
end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module SignInAfterConfirmation | |
extend ActiveSupport::Concern | |
included do | |
before_action :set_first_confirmation, only: :show | |
end | |
# GET /resource/confirmation?confirmation_token=abcdef | |
def show | |
super do |resource| | |
sign_in(resource) if sign_in_after_confirmation? | |
end | |
end | |
protected | |
def set_first_confirmation | |
# Is the User associated with this confirmation_token confirming their address | |
# for the first time? Or are they RE-confirming an address change? | |
# If this is the first time confirming, `confirmed_at` will be `nil`. | |
@first_confirmation = resource_class.where( | |
confirmation_token: params[:confirmation_token], | |
confirmed_at: nil | |
).exists? | |
end | |
def sign_in_after_confirmation? | |
# Devise executes #show when a user first confirms their address (i.e. after sign up) | |
# AND when a user reconfirms their address (i.e. after changing it). | |
# For security reasons, never sign in after reconfirmation. | |
# If the user made a typo when changing their email addres, they have | |
# inadvertantly given full account access to whoever owns that email address. | |
# The same problem exists for confirmations, but we're less concerned because | |
# there's no sensitive data in the account yet (it's brand new). | |
( | |
resource.errors.empty? && # Don't sign in invalid users. | |
@first_confirmation # Don't sign in reconfirmations. | |
) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment