Commit af4d722f authored by Nicolò Maria Mezzopera's avatar Nicolò Maria Mezzopera

Merge branch 'qa-shl-2fa-ui-recovery-specs' into 'master'

Add e2e spec for 2FA recovery via UI

Closes gitlab-org/quality/testcases#942

See merge request gitlab-org/gitlab!39076
parents 91bc80e9 2183e2af
......@@ -2,11 +2,11 @@
- lose_2fa_message = _('Should you ever lose your phone or access to your one time password secret, each of these recovery codes can be used one time each to regain access to your account. Please save them in a safe place, or you %{b_start}will%{b_end} lose access to your account.') % { b_start:'<b>', b_end:'</b>' }
= lose_2fa_message.html_safe
.codes.card
.codes.card{ data: { qa_selector: 'codes_content' } }
%ul
- @codes.each do |code|
%li
%span.monospace= code
%span.monospace{ data: { qa_selector: 'code_content' } }= code
.d-flex
= link_to _('Proceed'), profile_account_path, class: 'btn btn-success gl-mr-3', data: { qa_selector: 'proceed_button' }
......
......@@ -16,6 +16,8 @@ module QA
view 'app/views/profiles/two_factor_auths/_codes.html.haml' do
element :proceed_button
element :codes_content
element :code_content
end
def click_configure_it_later_button
......@@ -34,6 +36,13 @@ module QA
click_element :register_2fa_app_button
end
def recovery_codes
code_elements = within_element(:codes_content) do
all_elements(:code_content, minimum: 1)
end
code_elements.map { |code_content| code_content.text }
end
def click_proceed_button
click_element :proceed_button
end
......
......@@ -18,10 +18,12 @@ module QA
attribute :id
attribute :name
attribute :runners_token
attribute :require_two_factor_authentication
def initialize
@path = Runtime::Namespace.name
@description = "QA test run at #{Runtime::Namespace.time}"
@require_two_factor_authentication = false
end
def fabricate!
......@@ -72,7 +74,8 @@ module QA
parent_id: sandbox.id,
path: path,
name: path,
visibility: 'public'
visibility: 'public',
require_two_factor_authentication: @require_two_factor_authentication
}
end
......
# frozen_string_literal: true
module QA
context 'Manage', :requires_admin, :skip_live_env do
describe '2FA' do
let(:owner_user) do
Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_2fa_owner_username_1, Runtime::Env.gitlab_qa_2fa_owner_password_1)
end
let(:developer_user) do
Resource::User.fabricate_via_api! do |resource|
resource.api_client = admin_api_client
end
end
let(:sandbox_group) do
Resource::Sandbox.fabricate! do |sandbox_group|
sandbox_group.path = "gitlab-qa-2fa-recovery-sandbox-group-#{SecureRandom.hex(4)}"
sandbox_group.api_client = owner_api_client
end
end
let(:group) do
QA::Resource::Group.fabricate_via_api! do |group|
group.sandbox = sandbox_group
group.api_client = owner_api_client
group.require_two_factor_authentication = true
end
end
before do
group.add_member(developer_user, Resource::Members::AccessLevel::DEVELOPER)
end
it 'allows using 2FA recovery code once only' do
recovery_code = enable_2fa_for_user_and_fetch_recovery_code(developer_user)
Flow::Login.sign_in(as: developer_user, skip_page_validation: true)
Page::Main::TwoFactorAuth.perform do |two_fa_auth|
two_fa_auth.set_2fa_code(recovery_code)
two_fa_auth.click_verify_code_button
end
expect(Page::Main::Menu.perform(&:signed_in?)).to be_truthy
Page::Main::Menu.perform(&:sign_out)
Flow::Login.sign_in(as: developer_user, skip_page_validation: true)
Page::Main::TwoFactorAuth.perform do |two_fa_auth|
two_fa_auth.set_2fa_code(recovery_code)
two_fa_auth.click_verify_code_button
end
expect(page).to have_text('Invalid two-factor code')
end
after do
group.set_require_two_factor_authentication(value: 'false')
group.remove_via_api!
sandbox_group.remove_via_api!
developer_user.remove_via_api!
end
def admin_api_client
@admin_api_client ||= Runtime::API::Client.as_admin
end
def owner_api_client
@owner_api_client ||= Runtime::API::Client.new(:gitlab, user: owner_user)
end
def enable_2fa_for_user_and_fetch_recovery_code(user)
Flow::Login.while_signed_in(as: user) do
Page::Profile::TwoFactorAuth.perform do |two_fa_auth|
@otp = QA::Support::OTP.new(two_fa_auth.otp_secret_content)
two_fa_auth.set_pin_code(@otp.fresh_otp)
two_fa_auth.click_register_2fa_app_button
recovery_code = two_fa_auth.recovery_codes.sample
two_fa_auth.click_proceed_button
recovery_code
end
end
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