Commit c0c00782 authored by Vitaly Slobodin's avatar Vitaly Slobodin

Merge branch 'dblessing_missing_captchas' into 'master'

Add reCAPTCHA to password reset and confirmation email forms

See merge request gitlab-org/gitlab!72331
parents ee68fd89 6fa2efdf
# frozen_string_literal: true
module GitlabRecaptcha
extend ActiveSupport::Concern
include Recaptcha::Verify
include RecaptchaHelper
def load_recaptcha
recaptcha_enabled? && Gitlab::Recaptcha.load_configurations!
end
def check_recaptcha
return unless load_recaptcha
return if verify_recaptcha
flash[:alert] = _('There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.')
flash.delete :recaptcha_error
self.resource = resource_class.new
render action: 'new'
end
end
...@@ -2,6 +2,10 @@ ...@@ -2,6 +2,10 @@
class ConfirmationsController < Devise::ConfirmationsController class ConfirmationsController < Devise::ConfirmationsController
include AcceptsPendingInvitations include AcceptsPendingInvitations
include GitlabRecaptcha
prepend_before_action :check_recaptcha, only: :create
before_action :load_recaptcha, only: :new
feature_category :users feature_category :users
...@@ -31,6 +35,12 @@ class ConfirmationsController < Devise::ConfirmationsController ...@@ -31,6 +35,12 @@ class ConfirmationsController < Devise::ConfirmationsController
end end
end end
def check_recaptcha
return unless resource_params[:email].present?
super
end
def after_sign_in(resource) def after_sign_in(resource)
after_sign_in_path_for(resource) after_sign_in_path_for(resource)
end end
......
# frozen_string_literal: true # frozen_string_literal: true
class PasswordsController < Devise::PasswordsController class PasswordsController < Devise::PasswordsController
include GitlabRecaptcha
skip_before_action :require_no_authentication, only: [:edit, :update] skip_before_action :require_no_authentication, only: [:edit, :update]
prepend_before_action :check_recaptcha, only: :create
before_action :load_recaptcha, only: :new
before_action :resource_from_email, only: [:create] before_action :resource_from_email, only: [:create]
before_action :check_password_authentication_available, only: [:create] before_action :check_password_authentication_available, only: [:create]
before_action :throttle_reset, only: [:create] before_action :throttle_reset, only: [:create]
...@@ -59,6 +63,12 @@ class PasswordsController < Devise::PasswordsController ...@@ -59,6 +63,12 @@ class PasswordsController < Devise::PasswordsController
alert: _("Password authentication is unavailable.") alert: _("Password authentication is unavailable.")
end end
def check_recaptcha
return unless resource_params[:email].present?
super
end
def throttle_reset def throttle_reset
return unless resource && resource.recently_sent_password_reset? return unless resource && resource.recently_sent_password_reset?
......
# frozen_string_literal: true # frozen_string_literal: true
module RecaptchaHelper module RecaptchaHelper
def show_recaptcha_sign_up? def recaptcha_enabled?
!!Gitlab::Recaptcha.enabled? !!Gitlab::Recaptcha.enabled?
end end
alias_method :show_recaptcha_sign_up?, :recaptcha_enabled?
end end
RecaptchaHelper.prepend_mod RecaptchaHelper.prepend_mod
...@@ -7,7 +7,12 @@ ...@@ -7,7 +7,12 @@
.form-group .form-group
= f.label :email = f.label :email
= f.email_field :email, class: "form-control gl-form-input", required: true, title: _('Please provide a valid email address.'), value: nil = f.email_field :email, class: "form-control gl-form-input", required: true, title: _('Please provide a valid email address.'), value: nil
.clearfix
%div
- if recaptcha_enabled?
= recaptcha_tags nonce: content_security_policy_nonce
.gl-mt-5
= f.submit _("Resend"), class: 'gl-button btn btn-confirm' = f.submit _("Resend"), class: 'gl-button btn btn-confirm'
.clearfix.prepend-top-20 .clearfix.prepend-top-20
......
...@@ -8,7 +8,12 @@ ...@@ -8,7 +8,12 @@
= f.email_field :email, class: "form-control gl-form-input", required: true, value: params[:user_email], autofocus: true, title: _('Please provide a valid email address.') = f.email_field :email, class: "form-control gl-form-input", required: true, value: params[:user_email], autofocus: true, title: _('Please provide a valid email address.')
.form-text.text-muted .form-text.text-muted
= _('Requires your primary GitLab email address.') = _('Requires your primary GitLab email address.')
.clearfix
%div
- if recaptcha_enabled?
= recaptcha_tags nonce: content_security_policy_nonce
.gl-mt-5
= f.submit _("Reset password"), class: "gl-button btn-confirm btn" = f.submit _("Reset password"), class: "gl-button btn-confirm btn"
.clearfix.prepend-top-20 .clearfix.prepend-top-20
......
...@@ -123,4 +123,45 @@ RSpec.describe ConfirmationsController do ...@@ -123,4 +123,45 @@ RSpec.describe ConfirmationsController do
end end
end end
end end
describe '#create' do
let(:user) { create(:user) }
subject(:perform_request) { post(:create, params: { user: { email: user.email } }) }
context 'when reCAPTCHA is disabled' do
before do
stub_application_setting(recaptcha_enabled: false)
end
it 'successfully sends password reset when reCAPTCHA is not solved' do
perform_request
expect(response).to redirect_to(dashboard_projects_path)
end
end
context 'when reCAPTCHA is enabled' do
before do
stub_application_setting(recaptcha_enabled: true)
end
it 'displays an error when the reCAPTCHA is not solved' do
Recaptcha.configuration.skip_verify_env.delete('test')
perform_request
expect(response).to render_template(:new)
expect(flash[:alert]).to include 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'
end
it 'successfully sends password reset when reCAPTCHA is solved' do
Recaptcha.configuration.skip_verify_env << 'test'
perform_request
expect(response).to redirect_to(dashboard_projects_path)
end
end
end
end end
...@@ -91,4 +91,47 @@ RSpec.describe PasswordsController do ...@@ -91,4 +91,47 @@ RSpec.describe PasswordsController do
end end
end end
end end
describe '#create' do
let(:user) { create(:user) }
subject(:perform_request) { post(:create, params: { user: { email: user.email } }) }
context 'when reCAPTCHA is disabled' do
before do
stub_application_setting(recaptcha_enabled: false)
end
it 'successfully sends password reset when reCAPTCHA is not solved' do
perform_request
expect(response).to redirect_to(new_user_session_path)
expect(flash[:notice]).to include 'If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes.'
end
end
context 'when reCAPTCHA is enabled' do
before do
stub_application_setting(recaptcha_enabled: true)
end
it 'displays an error when the reCAPTCHA is not solved' do
Recaptcha.configuration.skip_verify_env.delete('test')
perform_request
expect(response).to render_template(:new)
expect(flash[:alert]).to include 'There was an error with the reCAPTCHA. Please solve the reCAPTCHA again.'
end
it 'successfully sends password reset when reCAPTCHA is solved' do
Recaptcha.configuration.skip_verify_env << 'test'
perform_request
expect(response).to redirect_to(new_user_session_path)
expect(flash[:notice]).to include 'If your email address exists in our database, you will receive a password recovery link at your email address in a few minutes.'
end
end
end
end end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'User confirmation' do
describe 'resend confirmation instructions' do
context 'when recaptcha is enabled' do
before do
stub_application_setting(recaptcha_enabled: true)
allow(Gitlab::Recaptcha).to receive(:load_configurations!)
visit new_user_confirmation_path
end
it 'renders recaptcha' do
expect(page).to have_css('.g-recaptcha')
end
end
context 'when recaptcha is not enabled' do
before do
stub_application_setting(recaptcha_enabled: false)
visit new_user_confirmation_path
end
it 'does not render recaptcha' do
expect(page).not_to have_css('.g-recaptcha')
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe 'User password' do
describe 'send password reset' do
context 'when recaptcha is enabled' do
before do
stub_application_setting(recaptcha_enabled: true)
allow(Gitlab::Recaptcha).to receive(:load_configurations!)
visit new_user_password_path
end
it 'renders recaptcha' do
expect(page).to have_css('.g-recaptcha')
end
end
context 'when recaptcha is not enabled' do
before do
stub_application_setting(recaptcha_enabled: false)
visit new_user_password_path
end
it 'does not render recaptcha' do
expect(page).not_to have_css('.g-recaptcha')
end
end
end
end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment