OpenProject is the leading open source project management software.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
openproject/spec/features/my_two_factor_devices_spec.rb

139 lines
5.3 KiB

require_relative '../spec_helper'
describe 'My Account 2FA configuration', type: :feature,
with_config: {:'2fa' => {active_strategies: [:developer, :totp]}},
js: true do
let(:dialog) { ::Components::PasswordConfirmationDialog.new }
let(:user_password) {'bob!' * 4}
let(:user) do
FactoryGirl.create(:user,
login: 'bob',
password: user_password,
password_confirmation: user_password,
)
end
before do
login_as user
end
it 'allows 2FA device management' do
# Visit empty index
visit my_2fa_devices_path
expect(page).to have_selector('.generic-table--empty-row', text: I18n.t('two_factor_authentication.devices.not_existing'))
expect(page).to have_selector('.on-off-status.-disabled')
# Visit inline create
find('.wp-inline-create--add-link').click
expect(page).to have_selector('h2', text: I18n.t('two_factor_authentication.devices.add_new'))
expect(current_path).to eq new_my_2fa_device_path
# Select SMS
find('.mobile-otp-new-device-sms .button').click
# Try to save with invalid phone number
fill_in 'device_phone_number', with: 'invalid!'
click_button I18n.t(:button_continue)
# Enter valid phone number
expect(page).to have_selector('#errorExplanation', text: 'Phone number must be of format +XX XXXXXXXXX')
fill_in 'device_phone_number', with: '+49 123456789'
click_button I18n.t(:button_continue)
# Fill in wrong token
fill_in 'otp', with: 'whatever'
# Log token for next access
sms_token = nil
allow_any_instance_of(::OpenProject::TwoFactorAuthentication::TokenStrategy::Developer)
.to receive(:create_mobile_otp).and_wrap_original do |m|
sms_token = m.call
end
click_button I18n.t(:button_continue)
expect(page).to have_selector('h2', text: I18n.t('two_factor_authentication.devices.confirm_device'))
expect(page).to have_selector('input#otp')
expect(page).to have_selector('.flash.error', text: I18n.t('two_factor_authentication.devices.registration_failed_token_invalid'))
# Fill in correct token
fill_in 'otp', with: sms_token
click_button I18n.t(:button_continue)
# Assert that it exists and is default
expect(page).to have_selector('.mobile-otp--two-factor-device-row td', text: 'Mobile phone (bob) (+49 123456789)')
expect(page).to have_selector('.mobile-otp--two-factor-device-row td .icon-yes', count: 2)
expect(page).to have_selector('.on-off-status.-enabled')
# Create another one as totp
# Visit create button
visit my_2fa_devices_path
find('.toolbar-item .button', text: '2FA device').click
expect(page).to have_selector('h2', text: I18n.t('two_factor_authentication.devices.add_new'))
expect(current_path).to eq new_my_2fa_device_path
# Select totp
find('.mobile-otp-new-device-totp .button').click
# Change identifier
fill_in 'device_identifier', with: 'custom identifier'
click_button I18n.t(:button_continue)
# Confirm token
expect(page).to have_selector('h2', text: I18n.t('two_factor_authentication.devices.confirm_device'))
expect(page).to have_selector('input#otp')
device = user.otp_devices.order(:id).last
expect(device.identifier).to eq 'custom identifier'
expect(device.default).to be_falsey
expect(device.active).to be_falsey
fill_in 'otp', with: device.totp.now
click_button I18n.t(:button_continue)
expect(page).to have_selector('.mobile-otp--two-factor-device-row', count: 2)
rows = page.all('.mobile-otp--two-factor-device-row')
expect(rows[0]).to have_selector('.mobile-otp--two-factor-device-row td .icon-yes', count: 2)
expect(rows[1]).to have_selector('.mobile-otp--two-factor-device-row td', text: 'custom identifier')
expect(rows[1]).to have_selector('.mobile-otp--two-factor-device-row td .icon-yes', count: 1)
device.reload
expect(device.active).to be_truthy
expect(device.default).to be_falsey
# Make the second one the default
# Confirm the password wrongly
find('.two-factor--mark-default-button').click
dialog.confirm_flow_with 'wrong_password', should_fail: true
# Confirm again
find('.two-factor--mark-default-button').click
dialog.confirm_flow_with user_password, should_fail: false
expect(page).to have_selector('.mobile-otp--two-factor-device-row', count: 2)
rows = page.all('.mobile-otp--two-factor-device-row')
expect(rows[0]).to have_selector('.mobile-otp--two-factor-device-row td .icon-yes', count: 1)
expect(rows[1]).to have_selector('.mobile-otp--two-factor-device-row td .icon-yes', count: 2)
device.reload
expect(device.default).to be_truthy
# Delete the sms device
rows[0].find('.two-factor--delete-button').click
dialog.confirm_flow_with user_password, should_fail: false
expect(page).to have_selector('.mobile-otp--two-factor-device-row', count: 1)
expect(page).to have_selector('.on-off-status.-enabled')
expect(user.otp_devices.count).to eq 1
# Delete the totp device
find('.two-factor--delete-button').click
dialog.confirm_flow_with user_password, should_fail: false
expect(page).to have_selector('.generic-table--empty-row', text: I18n.t('two_factor_authentication.devices.not_existing'))
expect(page).to have_selector('.on-off-status.-disabled')
expect(user.otp_devices.count).to eq 0
end
end