Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'spec/models/concerns/recoverable_by_any_email_spec.rb')
-rw-r--r--spec/models/concerns/recoverable_by_any_email_spec.rb131
1 files changed, 96 insertions, 35 deletions
diff --git a/spec/models/concerns/recoverable_by_any_email_spec.rb b/spec/models/concerns/recoverable_by_any_email_spec.rb
index 1e701f145be..ba0bb99effb 100644
--- a/spec/models/concerns/recoverable_by_any_email_spec.rb
+++ b/spec/models/concerns/recoverable_by_any_email_spec.rb
@@ -4,79 +4,140 @@ require 'spec_helper'
RSpec.describe RecoverableByAnyEmail, feature_category: :system_access do
describe '.send_reset_password_instructions' do
- let_it_be(:user) { create(:user, email: 'test@example.com') }
- let_it_be(:verified_email) { create(:email, :confirmed, user: user) }
- let_it_be(:unverified_email) { create(:email, user: user) }
+ include EmailHelpers
subject(:send_reset_password_instructions) do
User.send_reset_password_instructions(email: email)
end
- shared_examples 'sends the password reset email' do
+ let_it_be(:user) { create(:user) }
+ let_it_be(:user_confirmed_primary_email) { user.email }
+
+ let_it_be(:user_confirmed_secondary_email) do
+ create(:email, :confirmed, user: user, email: 'confirmed-secondary-email@example.com').email
+ end
+
+ let_it_be(:user_unconfirmed_secondary_email) do
+ create(:email, user: user, email: 'unconfirmed-secondary-email@example.com').email
+ end
+
+ let_it_be(:unknown_email) { 'attacker@example.com' }
+ let_it_be(:invalid_email) { 'invalid_email' }
+ let_it_be(:sql_injection_email) { 'sql-injection-email@example.com OR 1=1' }
+
+ let_it_be(:another_user_confirmed_primary_email) { create(:user).email }
+
+ let_it_be(:another_user) { create(:user, :unconfirmed) }
+ let_it_be(:another_user_unconfirmed_primary_email) { another_user.email }
+
+ shared_examples "sends 'Reset password instructions' email" do
it 'finds the user' do
- expect(send_reset_password_instructions).to eq(user)
+ expect(send_reset_password_instructions).to eq(expected_user)
end
it 'sends the email' do
+ reset_delivered_emails!
+
expect { send_reset_password_instructions }.to have_enqueued_mail(DeviseMailer, :reset_password_instructions)
+
+ perform_enqueued_jobs
+
+ expect_only_one_email_to_be_sent(subject: 'Reset password instructions', to: [email])
end
end
- shared_examples 'does not send the password reset email' do
+ shared_examples "does not send 'Reset password instructions' email" do
+ # If user is not found, returns a new user with errors.
+ # See https://github.com/heartcombo/devise/blob/main/lib/devise/models/recoverable.rb
it 'does not find the user' do
- expect(subject.id).to be_nil
- expect(subject.errors).not_to be_empty
+ expect(send_reset_password_instructions).to be_instance_of User
+ expect(send_reset_password_instructions).to be_new_record
+ expect(send_reset_password_instructions.errors).not_to be_empty
end
- it 'does not send any email' do
- subject
+ it 'does not send email to anyone' do
+ reset_delivered_emails!
+
+ expect { send_reset_password_instructions }
+ .not_to have_enqueued_mail(DeviseMailer, :reset_password_instructions)
+
+ perform_enqueued_jobs
- expect { subject }.not_to have_enqueued_mail(DeviseMailer, :reset_password_instructions)
+ should_not_email_anyone
end
end
- context 'with user primary email' do
- let(:email) { user.email }
+ context "when email param matches user's confirmed primary email" do
+ let(:expected_user) { user }
+ let(:email) { user_confirmed_primary_email }
- it_behaves_like 'sends the password reset email'
+ it_behaves_like "sends 'Reset password instructions' email"
end
- context 'with user verified email' do
- let(:email) { verified_email.email }
+ context "when email param matches user's unconfirmed primary email" do
+ let(:expected_user) { another_user }
+ let(:email) { another_user_unconfirmed_primary_email }
- it_behaves_like 'sends the password reset email'
+ it_behaves_like "sends 'Reset password instructions' email"
end
- context 'with user unverified email' do
- let(:email) { unverified_email.email }
+ context "when email param matches user's confirmed secondary email" do
+ let(:expected_user) { user }
+ let(:email) { user_confirmed_secondary_email }
- it_behaves_like 'does not send the password reset email'
+ it_behaves_like "sends 'Reset password instructions' email"
end
- end
- describe '#send_reset_password_instructions' do
- let_it_be(:user) { create(:user) }
- let_it_be(:opts) { { email: 'random@email.com' } }
- let_it_be(:token) { 'passwordresettoken' }
+ context "when email param matches user's unconfirmed secondary email" do
+ let(:email) { user_unconfirmed_secondary_email }
- before do
- allow(user).to receive(:set_reset_password_token).and_return(token)
+ it_behaves_like "does not send 'Reset password instructions' email"
end
- subject { user.send_reset_password_instructions(opts) }
+ context 'when email param is unknown email' do
+ let(:email) { unknown_email }
- it 'sends the email' do
- expect { subject }.to have_enqueued_mail(DeviseMailer, :reset_password_instructions)
+ it_behaves_like "does not send 'Reset password instructions' email"
end
- it 'calls send_reset_password_instructions_notification with correct arguments' do
- expect(user).to receive(:send_reset_password_instructions_notification).with(token, opts)
+ context 'when email param is invalid email' do
+ let(:email) { invalid_email }
- subject
+ it_behaves_like "does not send 'Reset password instructions' email"
end
- it 'returns the generated token' do
- expect(subject).to eq(token)
+ context 'when email param with attempt to cause SQL injection' do
+ let(:email) { sql_injection_email }
+
+ it_behaves_like "does not send 'Reset password instructions' email"
+ end
+
+ context 'when email param is nil' do
+ let(:email) { nil }
+
+ it_behaves_like "does not send 'Reset password instructions' email"
+ end
+
+ context 'when email param is empty string' do
+ let(:email) { '' }
+
+ it_behaves_like "does not send 'Reset password instructions' email"
+ end
+
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/436084
+ context 'when email param with multiple emails' do
+ let(:email) do
+ [
+ user_confirmed_primary_email,
+ user_confirmed_secondary_email,
+ user_unconfirmed_secondary_email,
+ unknown_email,
+ another_user_confirmed_primary_email,
+ another_user_unconfirmed_primary_email
+ ]
+ end
+
+ it_behaves_like "does not send 'Reset password instructions' email"
end
end
end