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/features/admin')
-rw-r--r--spec/features/admin/admin_abuse_reports_spec.rb2
-rw-r--r--spec/features/admin/admin_appearance_spec.rb287
-rw-r--r--spec/features/admin/admin_browse_spam_logs_spec.rb2
-rw-r--r--spec/features/admin/admin_deploy_keys_spec.rb2
-rw-r--r--spec/features/admin/admin_dev_ops_reports_spec.rb2
-rw-r--r--spec/features/admin/admin_disables_git_access_protocol_spec.rb2
-rw-r--r--spec/features/admin/admin_disables_two_factor_spec.rb4
-rw-r--r--spec/features/admin/admin_groups_spec.rb2
-rw-r--r--spec/features/admin/admin_health_check_spec.rb2
-rw-r--r--spec/features/admin/admin_hook_logs_spec.rb2
-rw-r--r--spec/features/admin/admin_hooks_spec.rb2
-rw-r--r--spec/features/admin/admin_jobs_spec.rb2
-rw-r--r--spec/features/admin/admin_labels_spec.rb2
-rw-r--r--spec/features/admin/admin_manage_applications_spec.rb2
-rw-r--r--spec/features/admin/admin_mode/login_spec.rb366
-rw-r--r--spec/features/admin/admin_mode/logout_spec.rb6
-rw-r--r--spec/features/admin/admin_mode/workers_spec.rb4
-rw-r--r--spec/features/admin/admin_mode_spec.rb53
-rw-r--r--spec/features/admin/admin_projects_spec.rb2
-rw-r--r--spec/features/admin/admin_runners_spec.rb2
-rw-r--r--spec/features/admin/admin_search_settings_spec.rb2
-rw-r--r--spec/features/admin/admin_sees_background_migrations_spec.rb2
-rw-r--r--spec/features/admin/admin_sees_project_statistics_spec.rb2
-rw-r--r--spec/features/admin/admin_sees_projects_statistics_spec.rb2
-rw-r--r--spec/features/admin/admin_settings_spec.rb2
-rw-r--r--spec/features/admin/admin_system_info_spec.rb2
-rw-r--r--spec/features/admin/admin_users_impersonation_tokens_spec.rb2
-rw-r--r--spec/features/admin/admin_users_spec.rb2
-rw-r--r--spec/features/admin/admin_uses_repository_checks_spec.rb2
-rw-r--r--spec/features/admin/broadcast_messages_spec.rb2
-rw-r--r--spec/features/admin/dashboard_spec.rb2
-rw-r--r--spec/features/admin/users/admin_impersonates_user_spec.rb208
-rw-r--r--spec/features/admin/users/admin_manages_user_identities_spec.rb56
-rw-r--r--spec/features/admin/users/admin_sees_unconfirmed_user_spec.rb52
-rw-r--r--spec/features/admin/users/admin_sees_user_spec.rb248
-rw-r--r--spec/features/admin/users/user_spec.rb537
-rw-r--r--spec/features/admin/users/users_spec.rb20
37 files changed, 957 insertions, 934 deletions
diff --git a/spec/features/admin/admin_abuse_reports_spec.rb b/spec/features/admin/admin_abuse_reports_spec.rb
index 5e98d2ffcf3..9c425f83508 100644
--- a/spec/features/admin/admin_abuse_reports_spec.rb
+++ b/spec/features/admin/admin_abuse_reports_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe "Admin::AbuseReports", :js, feature_category: :insider_threat do
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
visit admin_abuse_reports_path
end
diff --git a/spec/features/admin/admin_appearance_spec.rb b/spec/features/admin/admin_appearance_spec.rb
index 71c904b3a19..ec63e43d183 100644
--- a/spec/features/admin/admin_appearance_spec.rb
+++ b/spec/features/admin/admin_appearance_spec.rb
@@ -10,189 +10,180 @@ RSpec.describe 'Admin Appearance', feature_category: :shared do
stub_feature_flags(edit_user_profile_vue: false)
end
- flag_values = [true, false]
- flag_values.each do |val|
- context "with #{val}" do
- before do
- stub_feature_flags(restyle_login_page: val)
- end
+ it 'create new appearance' do
+ sign_in(admin)
+ enable_admin_mode!(admin)
+ visit admin_application_settings_appearances_path
+
+ fill_in 'appearance_title', with: 'MyCompany'
+ fill_in 'appearance_description', with: 'dev server'
+ fill_in 'appearance_pwa_name', with: 'GitLab PWA'
+ fill_in 'appearance_pwa_short_name', with: 'GitLab'
+ fill_in 'appearance_pwa_description', with: 'GitLab as PWA'
+ fill_in 'appearance_new_project_guidelines', with: 'Custom project guidelines'
+ fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines'
+ click_button 'Update appearance settings'
+
+ expect(page).to have_current_path admin_application_settings_appearances_path, ignore_query: true
+ expect(page).to have_content 'Appearance'
+
+ expect(page).to have_field('appearance_title', with: 'MyCompany')
+ expect(page).to have_field('appearance_description', with: 'dev server')
+ expect(page).to have_field('appearance_pwa_name', with: 'GitLab PWA')
+ expect(page).to have_field('appearance_pwa_short_name', with: 'GitLab')
+ expect(page).to have_field('appearance_pwa_description', with: 'GitLab as PWA')
+ expect(page).to have_field('appearance_new_project_guidelines', with: 'Custom project guidelines')
+ expect(page).to have_field('appearance_profile_image_guidelines', with: 'Custom profile image guidelines')
+ expect(page).to have_content 'Last edit'
+ end
- it 'create new appearance' do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- visit admin_application_settings_appearances_path
+ it 'preview sign-in page appearance' do
+ sign_in(admin)
+ enable_admin_mode!(admin)
- fill_in 'appearance_title', with: 'MyCompany'
- fill_in 'appearance_description', with: 'dev server'
- fill_in 'appearance_pwa_name', with: 'GitLab PWA'
- fill_in 'appearance_pwa_short_name', with: 'GitLab'
- fill_in 'appearance_pwa_description', with: 'GitLab as PWA'
- fill_in 'appearance_new_project_guidelines', with: 'Custom project guidelines'
- fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines'
- click_button 'Update appearance settings'
-
- expect(page).to have_current_path admin_application_settings_appearances_path, ignore_query: true
- expect(page).to have_content 'Appearance'
-
- expect(page).to have_field('appearance_title', with: 'MyCompany')
- expect(page).to have_field('appearance_description', with: 'dev server')
- expect(page).to have_field('appearance_pwa_name', with: 'GitLab PWA')
- expect(page).to have_field('appearance_pwa_short_name', with: 'GitLab')
- expect(page).to have_field('appearance_pwa_description', with: 'GitLab as PWA')
- expect(page).to have_field('appearance_new_project_guidelines', with: 'Custom project guidelines')
- expect(page).to have_field('appearance_profile_image_guidelines', with: 'Custom profile image guidelines')
- expect(page).to have_content 'Last edit'
- end
+ visit admin_application_settings_appearances_path
+ click_link "Sign-in page"
- it 'preview sign-in page appearance' do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ expect(find('#login')).to be_disabled
+ expect(find('#password')).to be_disabled
+ expect(find('button')).to be_disabled
- visit admin_application_settings_appearances_path
- click_link "Sign-in page"
+ expect_custom_sign_in_appearance(appearance)
+ end
- expect(find('#login')).to be_disabled
- expect(find('#password')).to be_disabled
- expect(find('button')).to be_disabled
+ it 'preview new project page appearance', :js do
+ sign_in(admin)
+ enable_admin_mode!(admin)
- expect_custom_sign_in_appearance(appearance)
- end
+ visit admin_application_settings_appearances_path
+ click_link "New project page"
+
+ expect_custom_new_project_appearance(appearance)
+ end
- it 'preview new project page appearance', :js do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ context 'Custom system header and footer' do
+ before do
+ sign_in(admin)
+ enable_admin_mode!(admin)
+ end
+ context 'when system header and footer messages are empty' do
+ it 'shows custom system header and footer fields' do
visit admin_application_settings_appearances_path
- click_link "New project page"
- expect_custom_new_project_appearance(appearance)
+ expect(page).to have_field('appearance_header_message', with: '')
+ expect(page).to have_field('appearance_footer_message', with: '')
+ expect(page).to have_field('appearance_message_background_color')
+ expect(page).to have_field('appearance_message_font_color')
end
+ end
- context 'Custom system header and footer' do
- before do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- end
-
- context 'when system header and footer messages are empty' do
- it 'shows custom system header and footer fields' do
- visit admin_application_settings_appearances_path
-
- expect(page).to have_field('appearance_header_message', with: '')
- expect(page).to have_field('appearance_footer_message', with: '')
- expect(page).to have_field('appearance_message_background_color')
- expect(page).to have_field('appearance_message_font_color')
- end
- end
-
- context 'when system header and footer messages are not empty' do
- before do
- appearance.update!(header_message: 'Foo', footer_message: 'Bar')
- end
-
- it 'shows custom system header and footer fields' do
- visit admin_application_settings_appearances_path
-
- expect(page).to have_field('appearance_header_message', with: appearance.header_message)
- expect(page).to have_field('appearance_footer_message', with: appearance.footer_message)
- expect(page).to have_field('appearance_message_background_color')
- expect(page).to have_field('appearance_message_font_color')
- end
- end
+ context 'when system header and footer messages are not empty' do
+ before do
+ appearance.update!(header_message: 'Foo', footer_message: 'Bar')
end
- it 'custom sign-in page' do
- visit new_user_session_path
+ it 'shows custom system header and footer fields' do
+ visit admin_application_settings_appearances_path
- expect_custom_sign_in_appearance(appearance)
+ expect(page).to have_field('appearance_header_message', with: appearance.header_message)
+ expect(page).to have_field('appearance_footer_message', with: appearance.footer_message)
+ expect(page).to have_field('appearance_message_background_color')
+ expect(page).to have_field('appearance_message_font_color')
end
+ end
+ end
- it 'custom new project page', :js do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- visit new_project_path
- click_link 'Create blank project'
+ it 'custom sign-in page' do
+ visit new_user_session_path
- expect_custom_new_project_appearance(appearance)
- end
+ expect_custom_sign_in_appearance(appearance)
+ end
- context 'Profile page with custom profile image guidelines' do
- before do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- visit admin_application_settings_appearances_path
- fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines, please :smile:!'
- click_button 'Update appearance settings'
- end
-
- it 'renders guidelines when set' do
- sign_in create(:user)
- visit profile_path
-
- expect(page).to have_content 'Custom profile image guidelines, please 😄!'
- end
- end
+ it 'custom new project page', :js do
+ sign_in(admin)
+ enable_admin_mode!(admin)
+ visit new_project_path
+ click_link 'Create blank project'
- it 'appearance logo' do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- visit admin_application_settings_appearances_path
+ expect_custom_new_project_appearance(appearance)
+ end
- attach_file(:appearance_logo, logo_fixture)
- click_button 'Update appearance settings'
- expect(page).to have_css(logo_selector)
+ context 'Profile page with custom profile image guidelines' do
+ before do
+ sign_in(admin)
+ enable_admin_mode!(admin)
+ visit admin_application_settings_appearances_path
+ fill_in 'appearance_profile_image_guidelines', with: 'Custom profile image guidelines, please :smile:!'
+ click_button 'Update appearance settings'
+ end
- click_link 'Remove logo'
- expect(page).not_to have_css(logo_selector)
- end
+ it 'renders guidelines when set' do
+ sign_in create(:user)
+ visit profile_path
- it 'appearance pwa icon' do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- visit admin_application_settings_appearances_path
+ expect(page).to have_content 'Custom profile image guidelines, please 😄!'
+ end
+ end
- attach_file(:appearance_pwa_icon, logo_fixture)
- click_button 'Update appearance settings'
- expect(page).to have_css(pwa_icon_selector)
+ it 'appearance logo' do
+ sign_in(admin)
+ enable_admin_mode!(admin)
+ visit admin_application_settings_appearances_path
- click_link 'Remove icon'
- expect(page).not_to have_css(pwa_icon_selector)
- end
+ attach_file(:appearance_logo, logo_fixture)
+ click_button 'Update appearance settings'
+ expect(page).to have_css(logo_selector)
- it 'header logos' do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- visit admin_application_settings_appearances_path
+ click_link 'Remove logo'
+ expect(page).not_to have_css(logo_selector)
+ end
- attach_file(:appearance_header_logo, logo_fixture)
- click_button 'Update appearance settings'
- expect(page).to have_css(header_logo_selector)
+ it 'appearance pwa icon' do
+ sign_in(admin)
+ enable_admin_mode!(admin)
+ visit admin_application_settings_appearances_path
- click_link 'Remove header logo'
- expect(page).not_to have_css(header_logo_selector)
- end
+ attach_file(:appearance_pwa_icon, logo_fixture)
+ click_button 'Update appearance settings'
+ expect(page).to have_css(pwa_icon_selector)
- it 'Favicon' do
- sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
- visit admin_application_settings_appearances_path
+ click_link 'Remove icon'
+ expect(page).not_to have_css(pwa_icon_selector)
+ end
- attach_file(:appearance_favicon, logo_fixture)
- click_button 'Update appearance settings'
+ it 'header logos' do
+ sign_in(admin)
+ enable_admin_mode!(admin)
+ visit admin_application_settings_appearances_path
- expect(page).to have_css('.appearance-light-logo-preview')
+ attach_file(:appearance_header_logo, logo_fixture)
+ click_button 'Update appearance settings'
+ expect(page).to have_css(header_logo_selector)
- click_link 'Remove favicon'
+ click_link 'Remove header logo'
+ expect(page).not_to have_css(header_logo_selector)
+ end
- expect(page).not_to have_css('.appearance-light-logo-preview')
+ it 'Favicon' do
+ sign_in(admin)
+ enable_admin_mode!(admin)
+ visit admin_application_settings_appearances_path
- # allowed file types
- attach_file(:appearance_favicon, Rails.root.join('spec', 'fixtures', 'sanitized.svg'))
- click_button 'Update appearance settings'
+ attach_file(:appearance_favicon, logo_fixture)
+ click_button 'Update appearance settings'
- expect(page).to have_content 'Favicon You are not allowed to upload "svg" files, allowed types: png, ico'
- end
- end
+ expect(page).to have_css('.appearance-light-logo-preview')
+
+ click_link 'Remove favicon'
+
+ expect(page).not_to have_css('.appearance-light-logo-preview')
+
+ # allowed file types
+ attach_file(:appearance_favicon, Rails.root.join('spec', 'fixtures', 'sanitized.svg'))
+ click_button 'Update appearance settings'
+
+ expect(page).to have_content 'Favicon You are not allowed to upload "svg" files, allowed types: png, ico'
end
def expect_custom_sign_in_appearance(appearance)
diff --git a/spec/features/admin/admin_browse_spam_logs_spec.rb b/spec/features/admin/admin_browse_spam_logs_spec.rb
index f781e2adf07..1f89232759c 100644
--- a/spec/features/admin/admin_browse_spam_logs_spec.rb
+++ b/spec/features/admin/admin_browse_spam_logs_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Admin browse spam logs', feature_category: :shared do
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
it 'browse spam logs' do
diff --git a/spec/features/admin/admin_deploy_keys_spec.rb b/spec/features/admin/admin_deploy_keys_spec.rb
index f9510ef296a..d6d021aeafc 100644
--- a/spec/features/admin/admin_deploy_keys_spec.rb
+++ b/spec/features/admin/admin_deploy_keys_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'admin deploy keys', :js, feature_category: :system_access do
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
it 'show all public deploy keys' do
diff --git a/spec/features/admin/admin_dev_ops_reports_spec.rb b/spec/features/admin/admin_dev_ops_reports_spec.rb
index 99d43e6b0da..e820ae866a1 100644
--- a/spec/features/admin/admin_dev_ops_reports_spec.rb
+++ b/spec/features/admin/admin_dev_ops_reports_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'DevOps Report page', :js, feature_category: :devops_reports do
before do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
context 'without licensed feature devops adoption' do
diff --git a/spec/features/admin/admin_disables_git_access_protocol_spec.rb b/spec/features/admin/admin_disables_git_access_protocol_spec.rb
index 76620b93557..039968025a9 100644
--- a/spec/features/admin/admin_disables_git_access_protocol_spec.rb
+++ b/spec/features/admin/admin_disables_git_access_protocol_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Admin disables Git access protocol', :js, feature_category: :sou
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
context 'with HTTP disabled' do
diff --git a/spec/features/admin/admin_disables_two_factor_spec.rb b/spec/features/admin/admin_disables_two_factor_spec.rb
index eed20d449cd..cb3c8973872 100644
--- a/spec/features/admin/admin_disables_two_factor_spec.rb
+++ b/spec/features/admin/admin_disables_two_factor_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Admin disables 2FA for a user', feature_category: :system_access
it 'successfully', :js do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
user = create(:user, :two_factor)
edit_user(user)
@@ -27,7 +27,7 @@ RSpec.describe 'Admin disables 2FA for a user', feature_category: :system_access
it 'for a user without 2FA enabled' do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
user = create(:user)
edit_user(user)
diff --git a/spec/features/admin/admin_groups_spec.rb b/spec/features/admin/admin_groups_spec.rb
index f071da1835a..283caddab6a 100644
--- a/spec/features/admin/admin_groups_spec.rb
+++ b/spec/features/admin/admin_groups_spec.rb
@@ -15,7 +15,7 @@ RSpec.describe 'Admin Groups', feature_category: :groups_and_projects do
before do
sign_in(current_user)
- gitlab_enable_admin_mode_sign_in(current_user)
+ enable_admin_mode!(current_user)
stub_application_setting(default_group_visibility: internal)
end
diff --git a/spec/features/admin/admin_health_check_spec.rb b/spec/features/admin/admin_health_check_spec.rb
index 66014e676d5..fa91159c5f5 100644
--- a/spec/features/admin/admin_health_check_spec.rb
+++ b/spec/features/admin/admin_health_check_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe "Admin Health Check", :js, feature_category: :error_budgets do
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
describe '#show' do
diff --git a/spec/features/admin/admin_hook_logs_spec.rb b/spec/features/admin/admin_hook_logs_spec.rb
index 0a537e65b99..146c83dbeee 100644
--- a/spec/features/admin/admin_hook_logs_spec.rb
+++ b/spec/features/admin/admin_hook_logs_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Admin::HookLogs', feature_category: :webhooks do
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
it 'show list of hook logs' do
diff --git a/spec/features/admin/admin_hooks_spec.rb b/spec/features/admin/admin_hooks_spec.rb
index 2aec5baf351..9bdb7ce000f 100644
--- a/spec/features/admin/admin_hooks_spec.rb
+++ b/spec/features/admin/admin_hooks_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe 'Admin::Hooks', feature_category: :webhooks do
before do
sign_in(user)
- gitlab_enable_admin_mode_sign_in(user)
+ enable_admin_mode!(user)
end
describe 'GET /admin/hooks' do
diff --git a/spec/features/admin/admin_jobs_spec.rb b/spec/features/admin/admin_jobs_spec.rb
index b3e21d02354..fc775c180ff 100644
--- a/spec/features/admin/admin_jobs_spec.rb
+++ b/spec/features/admin/admin_jobs_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Admin Jobs', :js, feature_category: :continuous_integration do
before do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
describe 'GET /admin/jobs' do
diff --git a/spec/features/admin/admin_labels_spec.rb b/spec/features/admin/admin_labels_spec.rb
index 47dc8577037..2fe68363062 100644
--- a/spec/features/admin/admin_labels_spec.rb
+++ b/spec/features/admin/admin_labels_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'admin issues labels', feature_category: :team_planning do
before do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
describe 'list' do
diff --git a/spec/features/admin/admin_manage_applications_spec.rb b/spec/features/admin/admin_manage_applications_spec.rb
index b4c77e802a8..3e351af6121 100644
--- a/spec/features/admin/admin_manage_applications_spec.rb
+++ b/spec/features/admin/admin_manage_applications_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe 'admin manage applications', feature_category: :system_access do
before do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
include_examples 'manage applications'
diff --git a/spec/features/admin/admin_mode/login_spec.rb b/spec/features/admin/admin_mode/login_spec.rb
index f2262464386..5298407deb3 100644
--- a/spec/features/admin/admin_mode/login_spec.rb
+++ b/spec/features/admin/admin_mode/login_spec.rb
@@ -13,256 +13,248 @@ RSpec.describe 'Admin Mode Login', feature_category: :system_access do
click_button 'Verify code'
end
- flag_values = [true, false]
- flag_values.each do |val|
- context "with #{val}" do
- before do
- stub_feature_flags(restyle_login_page: val)
- end
- context 'with valid username/password' do
- let(:user) { create(:admin, :two_factor) }
+ context 'with valid username/password' do
+ let(:user) { create(:admin, :two_factor) }
- context 'using one-time code' do
- it 'blocks login if we reuse the same code immediately' do
- gitlab_sign_in(user, remember: true)
+ context 'using one-time code' do
+ it 'blocks login if we reuse the same code immediately' do
+ gitlab_sign_in(user, remember: true)
- expect(page).to have_content(_('Enter verification code'))
+ expect(page).to have_content(_('Enter verification code'))
- repeated_otp = user.current_otp
- enter_code(repeated_otp)
- gitlab_enable_admin_mode_sign_in(user, use_mock_admin_mode: false)
+ repeated_otp = user.current_otp
+ enter_code(repeated_otp)
+ enable_admin_mode!(user, use_ui: true)
- expect(page).to have_content(_('Enter verification code'))
+ expect(page).to have_content(_('Enter verification code'))
- enter_code(repeated_otp)
+ enter_code(repeated_otp)
- expect(page).to have_current_path admin_session_path, ignore_query: true
- expect(page).to have_content('Invalid two-factor code')
- end
+ expect(page).to have_current_path admin_session_path, ignore_query: true
+ expect(page).to have_content('Invalid two-factor code')
+ end
- context 'not re-using codes' do
- before do
- gitlab_sign_in(user, remember: true)
+ context 'not re-using codes' do
+ before do
+ gitlab_sign_in(user, remember: true)
- expect(page).to have_content('Enter verification code')
+ expect(page).to have_content('Enter verification code')
- enter_code(user.current_otp)
- gitlab_enable_admin_mode_sign_in(user, use_mock_admin_mode: false)
+ enter_code(user.current_otp)
+ enable_admin_mode!(user, use_ui: true)
- expect(page).to have_content(_('Enter verification code'))
- end
+ expect(page).to have_content(_('Enter verification code'))
+ end
- it 'allows login with valid code' do
- # Cannot reuse the TOTP
- travel_to(30.seconds.from_now) do
- enter_code(user.current_otp)
+ it 'allows login with valid code' do
+ # Cannot reuse the TOTP
+ travel_to(30.seconds.from_now) do
+ enter_code(user.current_otp)
- expect(page).to have_current_path admin_root_path, ignore_query: true
- expect(page).to have_content('Admin mode enabled')
- end
- end
+ expect(page).to have_current_path admin_root_path, ignore_query: true
+ expect(page).to have_content('Admin mode enabled')
+ end
+ end
- it 'blocks login with invalid code' do
- # Cannot reuse the TOTP
- travel_to(30.seconds.from_now) do
- enter_code('foo')
+ it 'blocks login with invalid code' do
+ # Cannot reuse the TOTP
+ travel_to(30.seconds.from_now) do
+ enter_code('foo')
- expect(page).to have_content('Invalid two-factor code')
- end
- end
+ expect(page).to have_content('Invalid two-factor code')
+ end
+ end
- it 'allows login with invalid code, then valid code' do
- # Cannot reuse the TOTP
- travel_to(30.seconds.from_now) do
- enter_code('foo')
+ it 'allows login with invalid code, then valid code' do
+ # Cannot reuse the TOTP
+ travel_to(30.seconds.from_now) do
+ enter_code('foo')
- expect(page).to have_content('Invalid two-factor code')
+ expect(page).to have_content('Invalid two-factor code')
- enter_code(user.current_otp)
+ enter_code(user.current_otp)
- expect(page).to have_current_path admin_root_path, ignore_query: true
- expect(page).to have_content('Admin mode enabled')
- end
- end
+ expect(page).to have_current_path admin_root_path, ignore_query: true
+ expect(page).to have_content('Admin mode enabled')
+ end
+ end
- context 'using backup code' do
- let(:codes) { user.generate_otp_backup_codes! }
+ context 'using backup code' do
+ let(:codes) { user.generate_otp_backup_codes! }
- before do
- expect(codes.size).to eq 10
+ before do
+ expect(codes.size).to eq 10
- # Ensure the generated codes get saved
- user.save!
- end
+ # Ensure the generated codes get saved
+ user.save!
+ end
- context 'with valid code' do
- it 'allows login' do
- enter_code(codes.sample)
+ context 'with valid code' do
+ it 'allows login' do
+ enter_code(codes.sample)
- expect(page).to have_current_path admin_root_path, ignore_query: true
- expect(page).to have_content('Admin mode enabled')
- end
+ expect(page).to have_current_path admin_root_path, ignore_query: true
+ expect(page).to have_content('Admin mode enabled')
+ end
- it 'invalidates the used code' do
- expect { enter_code(codes.sample) }
- .to change { user.reload.otp_backup_codes.size }.by(-1)
- end
- end
+ it 'invalidates the used code' do
+ expect { enter_code(codes.sample) }
+ .to change { user.reload.otp_backup_codes.size }.by(-1)
+ end
+ end
- context 'with invalid code' do
- it 'blocks login' do
- code = codes.sample
- expect(user.invalidate_otp_backup_code!(code)).to eq true
+ context 'with invalid code' do
+ it 'blocks login' do
+ code = codes.sample
+ expect(user.invalidate_otp_backup_code!(code)).to eq true
- user.save!
- expect(user.reload.otp_backup_codes.size).to eq 9
+ user.save!
+ expect(user.reload.otp_backup_codes.size).to eq 9
- enter_code(code)
+ enter_code(code)
- expect(page).to have_content('Invalid two-factor code.')
- end
- end
+ expect(page).to have_content('Invalid two-factor code.')
end
end
end
+ end
+ end
- context 'when logging in via omniauth' do
- let(:user) { create(:omniauth_user, :admin, :two_factor, extern_uid: 'my-uid', provider: 'saml', password_automatically_set: false) }
- let(:mock_saml_response) do
- File.read('spec/fixtures/authentication/saml_response.xml')
- end
+ context 'when logging in via omniauth' do
+ let(:user) { create(:omniauth_user, :admin, :two_factor, extern_uid: 'my-uid', provider: 'saml', password_automatically_set: false) }
+ let(:mock_saml_response) do
+ File.read('spec/fixtures/authentication/saml_response.xml')
+ end
- before do
- stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config_with_upstream_two_factor_authn_contexts])
- end
+ before do
+ stub_omniauth_saml_config(enabled: true, auto_link_saml_user: true, allow_single_sign_on: ['saml'], providers: [mock_saml_config_with_upstream_two_factor_authn_contexts])
+ end
- context 'when authn_context is worth two factors' do
- let(:mock_saml_response) do
- File.read('spec/fixtures/authentication/saml_response.xml')
- .gsub(
- 'urn:oasis:names:tc:SAML:2.0:ac:classes:Password',
- 'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS'
- )
- end
+ context 'when authn_context is worth two factors' do
+ let(:mock_saml_response) do
+ File.read('spec/fixtures/authentication/saml_response.xml')
+ .gsub(
+ 'urn:oasis:names:tc:SAML:2.0:ac:classes:Password',
+ 'urn:oasis:names:tc:SAML:2.0:ac:classes:SecondFactorOTPSMS'
+ )
+ end
- it 'signs user in without prompting for second factor' do
- sign_in_using_saml!
+ it 'signs user in without prompting for second factor' do
+ sign_in_using_saml!
- expect(page).not_to have_content(_('Enter verification code'))
+ expect(page).not_to have_content(_('Enter verification code'))
- enable_admin_mode_using_saml!
+ enable_admin_mode_using_saml!
- expect(page).not_to have_content(_('Enter verification code'))
- expect(page).to have_current_path admin_root_path, ignore_query: true
- expect(page).to have_content('Admin mode enabled')
- end
- end
+ expect(page).not_to have_content(_('Enter verification code'))
+ expect(page).to have_current_path admin_root_path, ignore_query: true
+ expect(page).to have_content('Admin mode enabled')
+ end
+ end
- context 'when two factor authentication is required' do
- it 'shows 2FA prompt after omniauth login' do
- sign_in_using_saml!
+ context 'when two factor authentication is required' do
+ it 'shows 2FA prompt after omniauth login' do
+ sign_in_using_saml!
- expect(page).to have_content(_('Enter verification code'))
- enter_code(user.current_otp)
+ expect(page).to have_content(_('Enter verification code'))
+ enter_code(user.current_otp)
- enable_admin_mode_using_saml!
+ enable_admin_mode_using_saml!
- expect(page).to have_content(_('Enter verification code'))
+ expect(page).to have_content(_('Enter verification code'))
- # Cannot reuse the TOTP
- travel_to(30.seconds.from_now) do
- enter_code(user.current_otp)
+ # Cannot reuse the TOTP
+ travel_to(30.seconds.from_now) do
+ enter_code(user.current_otp)
- expect(page).to have_current_path admin_root_path, ignore_query: true
- expect(page).to have_content('Admin mode enabled')
- end
- end
+ expect(page).to have_current_path admin_root_path, ignore_query: true
+ expect(page).to have_content('Admin mode enabled')
end
+ end
+ end
- def sign_in_using_saml!
- gitlab_sign_in_via('saml', user, 'my-uid', mock_saml_response)
- end
+ def sign_in_using_saml!
+ gitlab_sign_in_via('saml', user, 'my-uid', mock_saml_response)
+ end
- def enable_admin_mode_using_saml!
- gitlab_enable_admin_mode_sign_in_via('saml', user, 'my-uid', mock_saml_response)
- end
- end
+ def enable_admin_mode_using_saml!
+ gitlab_enable_admin_mode_sign_in_via('saml', user, 'my-uid', mock_saml_response)
+ end
+ end
- context 'when logging in via ldap' do
- let(:uid) { 'my-uid' }
- let(:provider_label) { 'Main LDAP' }
- let(:provider_name) { 'main' }
- let(:provider) { "ldap#{provider_name}" }
- let(:ldap_server_config) do
- {
- 'label' => provider_label,
- 'provider_name' => provider,
- 'attributes' => {},
- 'encryption' => 'plain',
- 'uid' => 'uid',
- 'base' => 'dc=example,dc=com'
- }
- end
+ context 'when logging in via ldap' do
+ let(:uid) { 'my-uid' }
+ let(:provider_label) { 'Main LDAP' }
+ let(:provider_name) { 'main' }
+ let(:provider) { "ldap#{provider_name}" }
+ let(:ldap_server_config) do
+ {
+ 'label' => provider_label,
+ 'provider_name' => provider,
+ 'attributes' => {},
+ 'encryption' => 'plain',
+ 'uid' => 'uid',
+ 'base' => 'dc=example,dc=com'
+ }
+ end
- let(:user) { create(:omniauth_user, :admin, :two_factor, extern_uid: uid, provider: provider) }
+ let(:user) { create(:omniauth_user, :admin, :two_factor, extern_uid: uid, provider: provider) }
- before do
- setup_ldap(provider, user, uid, ldap_server_config)
- end
+ before do
+ setup_ldap(provider, user, uid, ldap_server_config)
+ end
- context 'when two factor authentication is required' do
- it 'shows 2FA prompt after ldap login' do
- sign_in_using_ldap!(user, provider_label)
- expect(page).to have_content(_('Enter verification code'))
+ context 'when two factor authentication is required' do
+ it 'shows 2FA prompt after ldap login' do
+ sign_in_using_ldap!(user, provider_label)
+ expect(page).to have_content(_('Enter verification code'))
- enter_code(user.current_otp)
- enable_admin_mode_using_ldap!(user)
+ enter_code(user.current_otp)
+ enable_admin_mode_using_ldap!(user)
- expect(page).to have_content(_('Enter verification code'))
+ expect(page).to have_content(_('Enter verification code'))
- # Cannot reuse the TOTP
- travel_to(30.seconds.from_now) do
- enter_code(user.current_otp)
+ # Cannot reuse the TOTP
+ travel_to(30.seconds.from_now) do
+ enter_code(user.current_otp)
- expect(page).to have_current_path admin_root_path, ignore_query: true
- expect(page).to have_content('Admin mode enabled')
- end
- end
+ expect(page).to have_current_path admin_root_path, ignore_query: true
+ expect(page).to have_content('Admin mode enabled')
end
+ end
+ end
- def setup_ldap(provider, user, uid, ldap_server_config)
- stub_ldap_setting(enabled: true)
+ def setup_ldap(provider, user, uid, ldap_server_config)
+ stub_ldap_setting(enabled: true)
- allow(::Gitlab::Auth::Ldap::Config).to receive_messages(enabled: true, servers: [ldap_server_config])
- allow(Gitlab::Auth::OAuth::Provider).to receive_messages(providers: [provider.to_sym])
+ allow(::Gitlab::Auth::Ldap::Config).to receive_messages(enabled: true, servers: [ldap_server_config])
+ allow(Gitlab::Auth::OAuth::Provider).to receive_messages(providers: [provider.to_sym])
- Ldap::OmniauthCallbacksController.define_providers!
- Rails.application.reload_routes!
+ Ldap::OmniauthCallbacksController.define_providers!
+ Rails.application.reload_routes!
- mock_auth_hash(provider, uid, user.email)
- allow(Gitlab::Auth::Ldap::Access).to receive(:allowed?).with(user).and_return(true)
+ mock_auth_hash(provider, uid, user.email)
+ allow(Gitlab::Auth::Ldap::Access).to receive(:allowed?).with(user).and_return(true)
- allow_any_instance_of(ActionDispatch::Routing::RoutesProxy)
- .to receive(:"user_#{provider}_omniauth_callback_path")
- .and_return("/users/auth/#{provider}/callback")
- end
+ allow_any_instance_of(ActionDispatch::Routing::RoutesProxy)
+ .to receive(:"user_#{provider}_omniauth_callback_path")
+ .and_return("/users/auth/#{provider}/callback")
+ end
- def sign_in_using_ldap!(user, provider_label)
- visit new_user_session_path
- click_link provider_label
- fill_in 'username', with: user.username
- fill_in 'password', with: user.password
- click_button 'Sign in'
- end
+ def sign_in_using_ldap!(user, provider_label)
+ visit new_user_session_path
+ click_link provider_label
+ fill_in 'username', with: user.username
+ fill_in 'password', with: user.password
+ click_button 'Sign in'
+ end
- def enable_admin_mode_using_ldap!(user)
- visit new_admin_session_path
- click_link provider_label
- fill_in 'username', with: user.username
- fill_in 'password', with: user.password
- click_button 'Enter admin mode'
- end
- end
+ def enable_admin_mode_using_ldap!(user)
+ visit new_admin_session_path
+ click_link provider_label
+ fill_in 'username', with: user.username
+ fill_in 'password', with: user.password
+ click_button 'Enter admin mode'
end
end
end
diff --git a/spec/features/admin/admin_mode/logout_spec.rb b/spec/features/admin/admin_mode/logout_spec.rb
index 584151726a6..aa0569b9f0d 100644
--- a/spec/features/admin/admin_mode/logout_spec.rb
+++ b/spec/features/admin/admin_mode/logout_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Admin Mode Logout', :js, feature_category: :system_access do
# TODO: This used to use gitlab_sign_in, instead of sign_in, but that is buggy. See
# this issue to look into why: https://gitlab.com/gitlab-org/gitlab/-/issues/331851
sign_in(user)
- gitlab_enable_admin_mode_sign_in(user, use_mock_admin_mode: false)
+ enable_admin_mode!(user, use_ui: true)
visit admin_root_path
end
@@ -21,7 +21,7 @@ RSpec.describe 'Admin Mode Logout', :js, feature_category: :system_access do
expect(page).to have_current_path root_path, ignore_query: true
- click_button 'Search or go to…'
+ find_by_testid('user-menu-toggle').click
expect(page).to have_link(href: new_admin_session_path)
end
@@ -42,7 +42,7 @@ RSpec.describe 'Admin Mode Logout', :js, feature_category: :system_access do
expect(page).to have_current_path root_path, ignore_query: true
- click_button 'Search or go to…'
+ find_by_testid('user-menu-toggle').click
expect(page).to have_link(href: new_admin_session_path)
end
diff --git a/spec/features/admin/admin_mode/workers_spec.rb b/spec/features/admin/admin_mode/workers_spec.rb
index 124c43eef9d..f0cea425bb7 100644
--- a/spec/features/admin/admin_mode/workers_spec.rb
+++ b/spec/features/admin/admin_mode/workers_spec.rb
@@ -34,7 +34,7 @@ RSpec.describe 'Admin mode for workers', :request_store, feature_category: :syst
context 'when admin mode enabled', :delete do
before do
- gitlab_enable_admin_mode_sign_in(user)
+ enable_admin_mode!(user)
end
it 'can delete user', :js do
@@ -67,6 +67,6 @@ RSpec.describe 'Admin mode for workers', :request_store, feature_category: :syst
Sidekiq::Worker.drain_all
sign_in(user)
- gitlab_enable_admin_mode_sign_in(user)
+ enable_admin_mode!(user)
end
end
diff --git a/spec/features/admin/admin_mode_spec.rb b/spec/features/admin/admin_mode_spec.rb
index 2a655cdb1f4..b58953989d2 100644
--- a/spec/features/admin/admin_mode_spec.rb
+++ b/spec/features/admin/admin_mode_spec.rb
@@ -20,18 +20,18 @@ RSpec.describe 'Admin mode', :js, feature_category: :shared do
context 'when not in admin mode' do
it 'has no leave admin mode button' do
visit new_admin_session_path
- open_search_modal
+ open_user_menu
expect(page).not_to have_link(href: destroy_admin_session_path)
end
it 'can open pages not in admin scope' do
visit new_admin_session_path
- open_search_modal
+ open_user_menu
- click_link('View all my projects')
+ click_link('Edit profile')
- expect(page).to have_current_path(dashboard_projects_path)
+ expect(page).to have_current_path(profile_path)
end
it 'is necessary to provide credentials again before opening pages in admin scope' do
@@ -41,11 +41,14 @@ RSpec.describe 'Admin mode', :js, feature_category: :shared do
end
it 'can enter admin mode' do
- visit new_admin_session_path
+ visit root_dashboard_path
+ open_user_menu
+ click_link 'Enter Admin Mode'
fill_in 'user_password', with: admin.password
click_button 'Enter admin mode'
+ click_link 'Admin Area'
expect(page).to have_current_path(admin_root_path)
end
@@ -69,38 +72,30 @@ RSpec.describe 'Admin mode', :js, feature_category: :shared do
context 'when in admin_mode' do
before do
- gitlab_enable_admin_mode_sign_in(admin, use_mock_admin_mode: false)
+ enable_admin_mode!(admin, use_ui: true)
end
it 'contains link to leave admin mode' do
- open_search_modal
-
- expect(page).to have_link(href: destroy_admin_session_path)
- end
-
- it 'can leave admin mode using main dashboard link' do
- gitlab_disable_admin_mode
-
- open_search_modal
-
- expect(page).to have_link(href: new_admin_session_path)
+ open_user_menu
+ click_link('Leave Admin Mode', href: destroy_admin_session_path)
+ expect(page).to have_text 'Admin mode disabled'
end
it 'can open pages not in admin scope' do
- open_search_modal
+ open_user_menu
- click_link('View all my projects')
+ click_link('Edit profile')
- expect(page).to have_current_path(dashboard_projects_path)
+ expect(page).to have_current_path(profile_path)
end
- context 'nav bar' do
- it 'shows admin dashboard links on bigger screen' do
+ context 'sidebar' do
+ it 'shows admin dashboard link' do
visit root_dashboard_path
- open_search_modal
- expect(page).to have_link(text: 'Admin', href: admin_root_path, visible: true)
- expect(page).to have_link(text: 'Leave admin mode', href: destroy_admin_session_path, visible: true)
+ within '#super-sidebar' do
+ expect(page).to have_link('Admin Area')
+ end
end
end
@@ -112,7 +107,7 @@ RSpec.describe 'Admin mode', :js, feature_category: :shared do
it 'can leave admin mode' do
gitlab_disable_admin_mode
- open_search_modal
+ open_user_menu
expect(page).to have_link(href: new_admin_session_path)
end
@@ -128,14 +123,14 @@ RSpec.describe 'Admin mode', :js, feature_category: :shared do
it 'shows no admin mode buttons in navbar' do
visit admin_root_path
- open_search_modal
+ open_user_menu
expect(page).not_to have_link(href: new_admin_session_path)
expect(page).not_to have_link(href: destroy_admin_session_path)
end
end
- def open_search_modal
- click_button 'Search or go to…'
+ def open_user_menu
+ find_by_testid('user-menu-toggle').click
end
end
diff --git a/spec/features/admin/admin_projects_spec.rb b/spec/features/admin/admin_projects_spec.rb
index b793299e253..978b2176431 100644
--- a/spec/features/admin/admin_projects_spec.rb
+++ b/spec/features/admin/admin_projects_spec.rb
@@ -14,7 +14,7 @@ RSpec.describe "Admin::Projects", feature_category: :groups_and_projects do
before do
sign_in(current_user)
- gitlab_enable_admin_mode_sign_in(current_user)
+ enable_admin_mode!(current_user)
end
describe 'when membership is set to expire', :js do
diff --git a/spec/features/admin/admin_runners_spec.rb b/spec/features/admin/admin_runners_spec.rb
index 653458710e3..2b4ceb05f00 100644
--- a/spec/features/admin/admin_runners_spec.rb
+++ b/spec/features/admin/admin_runners_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe "Admin Runners", feature_category: :fleet_visibility do
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
describe "Admin Runners page", :js do
diff --git a/spec/features/admin/admin_search_settings_spec.rb b/spec/features/admin/admin_search_settings_spec.rb
index 3254bf75738..c20a50cf218 100644
--- a/spec/features/admin/admin_search_settings_spec.rb
+++ b/spec/features/admin/admin_search_settings_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'Admin searches application settings', :js, feature_category: :gl
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
context 'in appearances page' do
diff --git a/spec/features/admin/admin_sees_background_migrations_spec.rb b/spec/features/admin/admin_sees_background_migrations_spec.rb
index ae307b8038c..43b920c657c 100644
--- a/spec/features/admin/admin_sees_background_migrations_spec.rb
+++ b/spec/features/admin/admin_sees_background_migrations_spec.rb
@@ -18,7 +18,7 @@ RSpec.describe "Admin > Admin sees background migrations", feature_category: :da
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
it 'can navigate to background migrations', :js do
diff --git a/spec/features/admin/admin_sees_project_statistics_spec.rb b/spec/features/admin/admin_sees_project_statistics_spec.rb
index d977735daf8..07f90d247cd 100644
--- a/spec/features/admin/admin_sees_project_statistics_spec.rb
+++ b/spec/features/admin/admin_sees_project_statistics_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe "Admin > Admin sees project statistics", feature_category: :group
before do
sign_in(current_user)
- gitlab_enable_admin_mode_sign_in(current_user)
+ enable_admin_mode!(current_user)
visit admin_project_path(project)
end
diff --git a/spec/features/admin/admin_sees_projects_statistics_spec.rb b/spec/features/admin/admin_sees_projects_statistics_spec.rb
index 3363a67ea90..cc6ccbab0a0 100644
--- a/spec/features/admin/admin_sees_projects_statistics_spec.rb
+++ b/spec/features/admin/admin_sees_projects_statistics_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe "Admin > Admin sees projects statistics", feature_category: :grou
create(:project, :repository) { |project| project.statistics.destroy! }
sign_in(current_user)
- gitlab_enable_admin_mode_sign_in(current_user)
+ enable_admin_mode!(current_user)
visit admin_projects_path
end
diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb
index 77707a67d58..d1fdbfc5329 100644
--- a/spec/features/admin/admin_settings_spec.rb
+++ b/spec/features/admin/admin_settings_spec.rb
@@ -13,7 +13,7 @@ RSpec.describe 'Admin updates settings', feature_category: :shared do
before do
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin, use_mock_admin_mode: false)
+ enable_admin_mode!(admin, use_ui: true)
end
context 'General page' do
diff --git a/spec/features/admin/admin_system_info_spec.rb b/spec/features/admin/admin_system_info_spec.rb
index 71a0b829932..f285fefe6db 100644
--- a/spec/features/admin/admin_system_info_spec.rb
+++ b/spec/features/admin/admin_system_info_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe 'Admin System Info', feature_category: :shared do
before do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
describe 'GET /admin/system_info' do
diff --git a/spec/features/admin/admin_users_impersonation_tokens_spec.rb b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
index 543dc2cc2a6..7cfe0cdbc81 100644
--- a/spec/features/admin/admin_users_impersonation_tokens_spec.rb
+++ b/spec/features/admin/admin_users_impersonation_tokens_spec.rb
@@ -11,7 +11,7 @@ RSpec.describe 'Admin > Users > Impersonation Tokens', :js, feature_category: :s
before do
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
describe "token creation" do
diff --git a/spec/features/admin/admin_users_spec.rb b/spec/features/admin/admin_users_spec.rb
index 9ab5b1fd3bb..f09c1a59b0d 100644
--- a/spec/features/admin/admin_users_spec.rb
+++ b/spec/features/admin/admin_users_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe "Admin::Users", feature_category: :user_management do
before do
sign_in(current_user)
- gitlab_enable_admin_mode_sign_in(current_user)
+ enable_admin_mode!(current_user)
end
describe 'Tabs' do
diff --git a/spec/features/admin/admin_uses_repository_checks_spec.rb b/spec/features/admin/admin_uses_repository_checks_spec.rb
index 05232de35e5..a628344bfeb 100644
--- a/spec/features/admin/admin_uses_repository_checks_spec.rb
+++ b/spec/features/admin/admin_uses_repository_checks_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe 'Admin uses repository checks', :request_store, feature_category:
context 'when admin mode is enabled' do
before do
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
it 'to trigger a single check', :js do
diff --git a/spec/features/admin/broadcast_messages_spec.rb b/spec/features/admin/broadcast_messages_spec.rb
index e4a2e31ee1c..16651ffa07e 100644
--- a/spec/features/admin/broadcast_messages_spec.rb
+++ b/spec/features/admin/broadcast_messages_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe 'Admin Broadcast Messages', :js, feature_category: :onboarding do
it 'previews, creates and edits a broadcast message' do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
# create
visit admin_broadcast_messages_path
diff --git a/spec/features/admin/dashboard_spec.rb b/spec/features/admin/dashboard_spec.rb
index 06f9c531e74..9e8f5138815 100644
--- a/spec/features/admin/dashboard_spec.rb
+++ b/spec/features/admin/dashboard_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe 'admin visits dashboard' do
before do
admin = create(:admin)
sign_in(admin)
- gitlab_enable_admin_mode_sign_in(admin)
+ enable_admin_mode!(admin)
end
context 'counting forks', :js, feature_category: :source_code_management do
diff --git a/spec/features/admin/users/admin_impersonates_user_spec.rb b/spec/features/admin/users/admin_impersonates_user_spec.rb
new file mode 100644
index 00000000000..e37b4bf1562
--- /dev/null
+++ b/spec/features/admin/users/admin_impersonates_user_spec.rb
@@ -0,0 +1,208 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Admin impersonates user', feature_category: :user_management do
+ let_it_be(:user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') }
+ let_it_be(:current_user) { create(:admin) }
+
+ before do
+ sign_in(current_user)
+ enable_admin_mode!(current_user, use_ui: true)
+ end
+
+ describe 'GET /admin/users/:id' do
+ describe 'Impersonation' do
+ let_it_be(:another_user) { create(:user) }
+
+ context 'before impersonating' do
+ subject { visit admin_user_path(user_to_visit) }
+
+ let_it_be(:user_to_visit) { another_user }
+
+ shared_examples "user that cannot be impersonated" do
+ it 'disables impersonate button' do
+ subject
+
+ impersonate_btn = find_by_testid('impersonate-user-link')
+
+ expect(impersonate_btn).not_to be_nil
+ expect(impersonate_btn['disabled']).not_to be_nil
+ end
+
+ it "shows tooltip with correct error message" do
+ subject
+
+ expect(find("span[title='#{impersonation_error_msg}']")).not_to be_nil
+ end
+ end
+
+ context 'for other users' do
+ it 'shows impersonate button for other users' do
+ subject
+
+ expect(page).to have_content('Impersonate')
+ impersonate_btn = find_by_testid('impersonate-user-link')
+ expect(impersonate_btn['disabled']).to be_nil
+ end
+ end
+
+ context 'for admin itself' do
+ let(:user_to_visit) { current_user }
+
+ it 'does not show impersonate button for admin itself' do
+ subject
+
+ expect(page).to have_no_content('Impersonate')
+ end
+ end
+
+ context 'for blocked user' do
+ let_it_be(:blocked_user) { create(:user, :blocked) }
+ let(:user_to_visit) { blocked_user }
+ let(:impersonation_error_msg) { _('You cannot impersonate a blocked user') }
+
+ it_behaves_like "user that cannot be impersonated"
+ end
+
+ context 'for user with expired password' do
+ let_it_be(:user_to_visit) do
+ another_user.update!(password_expires_at: Time.zone.now - 5.minutes)
+ another_user
+ end
+
+ let(:impersonation_error_msg) { _("You cannot impersonate a user with an expired password") }
+
+ it_behaves_like "user that cannot be impersonated"
+ end
+
+ context 'for internal user' do
+ let_it_be(:internal_user) { create(:user, :bot) }
+ let(:user_to_visit) { internal_user }
+ let(:impersonation_error_msg) { _("You cannot impersonate an internal user") }
+
+ it_behaves_like "user that cannot be impersonated"
+ end
+
+ context 'for locked user' do
+ let_it_be(:locked_user) { create(:user, :locked) }
+ let(:user_to_visit) { locked_user }
+ let(:impersonation_error_msg) { _("You cannot impersonate a user who cannot log in") }
+
+ it_behaves_like "user that cannot be impersonated"
+ end
+
+ context 'when already impersonating another user' do
+ let_it_be(:admin_user) { create(:user, :admin) }
+ let(:impersonation_error_msg) { _("You are already impersonating another user") }
+
+ subject do
+ visit admin_user_path(admin_user)
+ click_link 'Impersonate'
+ visit admin_user_path(another_user)
+ end
+
+ it_behaves_like "user that cannot be impersonated"
+ end
+
+ context 'when impersonation is disabled' do
+ before do
+ stub_config_setting(impersonation_enabled: false)
+ end
+
+ it 'does not show impersonate button' do
+ subject
+
+ expect(page).to have_no_content('Impersonate')
+ end
+ end
+ end
+
+ context 'when impersonating' do
+ subject { click_link 'Impersonate' }
+
+ before do
+ visit admin_user_path(another_user)
+ end
+
+ it 'logs in as the user when impersonate is clicked', :js do
+ subject
+
+ expect(page).to have_button("#{another_user.name} user’s menu")
+ end
+
+ it 'sees impersonation log out icon', :js do
+ subject
+
+ icon = first('[data-testid="incognito-icon"]')
+ expect(icon).not_to be nil
+ end
+
+ context 'when viewing the confirm email warning', :js do
+ before do
+ stub_application_setting_enum('email_confirmation_setting', 'soft')
+ end
+
+ let_it_be(:another_user) { create(:user, :unconfirmed) }
+ let(:warning_alert) { page.find(:css, '[data-testid="alert-warning"]') }
+
+ context 'with an email that does not contain HTML' do
+ before do
+ subject
+ end
+
+ it 'displays the warning alert including the email' do
+ expect(warning_alert.text).to include("Please check your email (#{another_user.email}) to verify")
+ end
+ end
+
+ context 'with an email that contains HTML' do
+ let(:malicious_email) { "malicious@test.com<form><input/title='<script>alert(document.domain)</script>'>" }
+ let(:another_user) { create(:user, confirmed_at: nil, unconfirmed_email: malicious_email) }
+
+ before do
+ subject
+ end
+
+ it 'displays the impersonation alert, excludes email, and disables links' do
+ expect(warning_alert.text).to include("check your email (#{another_user.unconfirmed_email}) to verify")
+ end
+ end
+ end
+ end
+
+ context 'ending impersonation', :js do
+ subject { click_on 'Stop impersonating' }
+
+ before do
+ visit admin_user_path(another_user)
+ click_link 'Impersonate'
+ end
+
+ it 'logs out of impersonated user back to original user' do
+ subject
+
+ expect(page).to have_button("#{current_user.name} user’s menu")
+ end
+
+ it 'is redirected back to the impersonated users page in the admin after stopping' do
+ subject
+
+ expect(page).to have_current_path("/admin/users/#{another_user.username}", ignore_query: true)
+ end
+
+ context 'a user with an expired password' do
+ before do
+ another_user.update!(password_expires_at: Time.zone.now - 5.minutes)
+ end
+
+ it 'is redirected back to the impersonated users page in the admin after stopping' do
+ subject
+
+ expect(page).to have_current_path("/admin/users/#{another_user.username}", ignore_query: true)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/spec/features/admin/users/admin_manages_user_identities_spec.rb b/spec/features/admin/users/admin_manages_user_identities_spec.rb
new file mode 100644
index 00000000000..cbb7eed9e1c
--- /dev/null
+++ b/spec/features/admin/users/admin_manages_user_identities_spec.rb
@@ -0,0 +1,56 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Admin manages user identities', feature_category: :user_management do
+ let_it_be(:user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') }
+ let_it_be(:current_user) { create(:admin) }
+
+ before do
+ sign_in(current_user)
+ enable_admin_mode!(current_user, use_ui: true)
+ end
+
+ describe 'GET /admin/users/:id' do
+ describe 'show user identities' do
+ it 'shows user identities', :aggregate_failures do
+ visit admin_user_identities_path(user)
+
+ expect(page).to(
+ have_content(user.name)
+ .and(have_content('twitter'))
+ )
+ end
+ end
+
+ describe 'update user identities' do
+ before do
+ allow(Gitlab::Auth::OAuth::Provider).to receive(:providers).and_return([:twitter, :twitter_updated])
+ end
+
+ it 'modifies twitter identity', :aggregate_failures do
+ visit admin_user_identities_path(user)
+
+ find('.table').find(:link, 'Edit').click
+ fill_in 'identity_extern_uid', with: '654321'
+ select 'twitter_updated', from: 'identity_provider'
+ click_button 'Save changes'
+
+ expect(page).to have_content(user.name)
+ expect(page).to have_content('twitter_updated')
+ expect(page).to have_content('654321')
+ end
+ end
+
+ describe 'remove user with identities' do
+ it 'removes user with twitter identity', :aggregate_failures do
+ visit admin_user_identities_path(user)
+
+ click_link 'Delete'
+
+ expect(page).to have_content(user.name)
+ expect(page).not_to have_content('twitter')
+ end
+ end
+ end
+end
diff --git a/spec/features/admin/users/admin_sees_unconfirmed_user_spec.rb b/spec/features/admin/users/admin_sees_unconfirmed_user_spec.rb
new file mode 100644
index 00000000000..7b45e5b5cde
--- /dev/null
+++ b/spec/features/admin/users/admin_sees_unconfirmed_user_spec.rb
@@ -0,0 +1,52 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Admin sees unconfirmed user', feature_category: :user_management do
+ include Spec::Support::Helpers::ModalHelpers
+
+ let_it_be(:user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') }
+ let_it_be(:current_user) { create(:admin) }
+
+ before do
+ sign_in(current_user)
+ enable_admin_mode!(current_user, use_ui: true)
+ end
+
+ context 'when user has an unconfirmed email', :js do
+ # Email address contains HTML to ensure email address is displayed in an HTML safe way.
+ let_it_be(:unconfirmed_email) { "#{generate(:email)}<h2>testing<img/src=http://localhost:8000/test.png>" }
+ let_it_be(:unconfirmed_user) { create(:user, :unconfirmed, unconfirmed_email: unconfirmed_email) }
+
+ where(:path_helper) do
+ [
+ [-> (user) { admin_user_path(user) }],
+ [-> (user) { projects_admin_user_path(user) }],
+ [-> (user) { keys_admin_user_path(user) }],
+ [-> (user) { admin_user_identities_path(user) }],
+ [-> (user) { admin_user_impersonation_tokens_path(user) }]
+ ]
+ end
+
+ with_them do
+ it "allows an admin to force confirmation of the user's email", :aggregate_failures do
+ visit path_helper.call(unconfirmed_user)
+
+ click_button 'Confirm user'
+
+ within_modal do
+ expect(page).to have_content("Confirm user #{unconfirmed_user.name}?")
+ expect(page).to(
+ have_content(
+ "This user has an unconfirmed email address (#{unconfirmed_email}). You may force a confirmation.")
+ )
+
+ click_button 'Confirm user'
+ end
+
+ expect(page).to have_content('Successfully confirmed')
+ expect(page).not_to have_button('Confirm user')
+ end
+ end
+ end
+end
diff --git a/spec/features/admin/users/admin_sees_user_spec.rb b/spec/features/admin/users/admin_sees_user_spec.rb
new file mode 100644
index 00000000000..d8c142d402f
--- /dev/null
+++ b/spec/features/admin/users/admin_sees_user_spec.rb
@@ -0,0 +1,248 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe 'Admin::Users::User', feature_category: :user_management do
+ include Features::AdminUsersHelpers
+ include Spec::Support::Helpers::ModalHelpers
+
+ let_it_be(:user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') }
+ let_it_be(:current_user) { create(:admin) }
+
+ before do
+ sign_in(current_user)
+ enable_admin_mode!(current_user, use_ui: true)
+ end
+
+ describe 'GET /admin/users/:id' do
+ it 'has user info', :js, :aggregate_failures do
+ visit admin_user_path(user)
+
+ expect(page).to have_content(user.email)
+ expect(page).to have_content(user.name)
+ expect(page).to have_content("ID: #{user.id}")
+ expect(page).to have_content("Namespace ID: #{user.namespace_id}")
+
+ click_user_dropdown_toggle(user.id)
+
+ expect(page).to have_button('Block')
+ expect(page).to have_button('Deactivate')
+ expect(page).to have_button('Delete user')
+ expect(page).to have_button('Delete user and contributions')
+ end
+
+ context 'when blocking/unblocking the user' do
+ it 'shows confirmation and allows blocking and unblocking', :js do
+ visit admin_user_path(user)
+
+ click_action_in_user_dropdown(user.id, 'Block')
+
+ expect(page).to have_content('Block user')
+ expect(page).to have_content('You can always unblock their account, their data will remain intact.')
+
+ find('.modal-footer button', text: 'Block').click
+
+ wait_for_requests
+
+ expect(page).to have_content('Successfully blocked')
+
+ click_action_in_user_dropdown(user.id, 'Unblock')
+
+ expect(page).to have_content('Unblock user')
+ expect(page).to have_content('You can always block their account again if needed.')
+
+ find('.modal-footer button', text: 'Unblock').click
+
+ expect(page).to have_content('Successfully unblocked')
+
+ click_user_dropdown_toggle(user.id)
+ expect(page).to have_content('Block')
+ end
+ end
+
+ context 'when deactivating/re-activating the user' do
+ it 'shows confirmation and allows deactivating/re-activating', :js do
+ visit admin_user_path(user)
+
+ click_action_in_user_dropdown(user.id, 'Deactivate')
+
+ expect(page).to have_content('Deactivate user')
+ expect(page).to have_content('You can always re-activate their account, their data will remain intact.')
+
+ find('.modal-footer button', text: 'Deactivate').click
+
+ wait_for_requests
+
+ expect(page).to have_content('Successfully deactivated')
+
+ click_action_in_user_dropdown(user.id, 'Activate')
+
+ expect(page).to have_content('Activate user')
+ expect(page).to have_content('You can always deactivate their account again if needed.')
+
+ find('.modal-footer button', text: 'Activate').click
+
+ wait_for_requests
+
+ expect(page).to have_content('Successfully activated')
+
+ click_user_dropdown_toggle(user.id)
+ expect(page).to have_content('Deactivate')
+ end
+ end
+
+ context 'when user is the sole owner of a group' do
+ let_it_be(:group) { create(:group) }
+ let_it_be(:user_sole_owner_of_group) { create(:user) }
+
+ before do
+ group.add_owner(user_sole_owner_of_group)
+ end
+
+ it 'shows `Delete user and contributions` action but not `Delete user` action', :js do
+ visit admin_user_path(user_sole_owner_of_group)
+
+ click_user_dropdown_toggle(user_sole_owner_of_group.id)
+
+ expect(page).to have_button('Delete user and contributions')
+ expect(page).not_to have_button('Delete user', exact: true)
+ end
+
+ it 'allows user to be deleted by using the `Delete user and contributions` action', :js do
+ visit admin_user_path(user_sole_owner_of_group)
+
+ click_action_in_user_dropdown(user_sole_owner_of_group.id, 'Delete user and contributions')
+
+ within_modal do
+ fill_in('username', with: user_sole_owner_of_group.name)
+ click_button('Delete user and contributions')
+ end
+
+ wait_for_requests
+
+ expect(page).to have_content('The user is being deleted.')
+ end
+ end
+
+ context 'when a user is locked', time_travel_to: '2020-02-02 10:30:45 -0700' do
+ let_it_be(:locked_user) { create(:user, locked_at: DateTime.parse('2020-02-02 10:30:00 -0700')) }
+
+ before do
+ visit admin_user_path(locked_user)
+ end
+
+ it "displays `(Locked)` next to user's name" do
+ expect(page).to have_content("#{locked_user.name} (Locked)")
+ end
+
+ it 'allows a user to be unlocked from the `User administration dropdown', :js do
+ accept_gl_confirm("Unlock user #{locked_user.name}?", button_text: 'Unlock') do
+ click_action_in_user_dropdown(locked_user.id, 'Unlock')
+ end
+
+ expect(page).not_to have_content("#{locked_user.name} (Locked)")
+ end
+ end
+
+ describe 'Two-factor Authentication status' do
+ it 'shows when enabled' do
+ user.update!(otp_required_for_login: true)
+
+ visit admin_user_path(user)
+
+ expect_two_factor_status('Enabled')
+ end
+
+ it 'shows when disabled' do
+ user.update!(otp_required_for_login: false)
+
+ visit admin_user_path(user)
+
+ expect_two_factor_status('Disabled')
+ end
+
+ def expect_two_factor_status(status)
+ page.within('.two-factor-status') do
+ expect(page).to have_content(status)
+ end
+ end
+ end
+
+ describe 'Email verification status' do
+ let_it_be(:secondary_email) do
+ create :email, email: 'secondary@example.com', user: user
+ end
+
+ it 'displays the correct status for an unverified email address', :aggregate_failures do
+ user.update!(confirmed_at: nil, unconfirmed_email: user.email)
+ visit admin_user_path(user)
+
+ expect(page).to have_content("#{user.email} Unverified")
+ expect(page).to have_content("#{secondary_email.email} Unverified")
+ end
+
+ it 'displays the correct status for a verified email address' do
+ visit admin_user_path(user)
+ expect(page).to have_content("#{user.email} Verified")
+
+ secondary_email.confirm
+ expect(secondary_email.confirmed?).to be_truthy
+
+ visit admin_user_path(user)
+ expect(page).to have_content("#{secondary_email.email} Verified")
+ end
+ end
+
+ describe 'remove users secondary email', :js do
+ let_it_be(:secondary_email) do
+ create :email, email: 'secondary@example.com', user: user
+ end
+
+ it do
+ visit admin_user_path(user.username)
+
+ expect(page).to have_content("Secondary email: #{secondary_email.email}")
+
+ accept_gl_confirm { find("#remove_email_#{secondary_email.id}").click }
+
+ expect(page).not_to have_content(secondary_email.email)
+ end
+ end
+
+ describe 'show user keys', :js do
+ it do
+ key1 = create(:key, user: user, title: 'ssh-rsa Key1')
+ key2 = create(:key, user: user, title: 'ssh-rsa Key2')
+
+ visit admin_user_path(user)
+
+ click_link 'SSH keys'
+
+ expect(page).to have_content(key1.title)
+ expect(page).to have_content(key2.title)
+
+ click_link key2.title
+
+ expect(page).to have_content(key2.title)
+ expect(page).to have_content(key2.key)
+
+ click_button 'Delete'
+
+ page.within('.modal') do
+ page.click_button('Delete')
+ end
+
+ expect(page).not_to have_content(key2.title)
+ end
+ end
+
+ describe 'show user attributes' do
+ it 'has expected attributes', :aggregate_failures do
+ visit admin_user_path(user)
+
+ expect(page).to have_content 'Account'
+ expect(page).to have_content 'Personal projects limit'
+ end
+ end
+ end
+end
diff --git a/spec/features/admin/users/user_spec.rb b/spec/features/admin/users/user_spec.rb
deleted file mode 100644
index d0110b3e013..00000000000
--- a/spec/features/admin/users/user_spec.rb
+++ /dev/null
@@ -1,537 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'Admin::Users::User', feature_category: :user_management do
- include Features::AdminUsersHelpers
- include Spec::Support::Helpers::ModalHelpers
-
- let_it_be(:user) { create(:omniauth_user, provider: 'twitter', extern_uid: '123456') }
- let_it_be(:current_user) { create(:admin) }
-
- before do
- sign_in(current_user)
- gitlab_enable_admin_mode_sign_in(current_user, use_mock_admin_mode: false)
- end
-
- describe 'GET /admin/users/:id' do
- it 'has user info', :js, :aggregate_failures do
- visit admin_user_path(user)
-
- expect(page).to have_content(user.email)
- expect(page).to have_content(user.name)
- expect(page).to have_content("ID: #{user.id}")
- expect(page).to have_content("Namespace ID: #{user.namespace_id}")
-
- click_user_dropdown_toggle(user.id)
-
- expect(page).to have_button('Block')
- expect(page).to have_button('Deactivate')
- expect(page).to have_button('Delete user')
- expect(page).to have_button('Delete user and contributions')
- end
-
- context 'when blocking/unblocking the user' do
- it 'shows confirmation and allows blocking and unblocking', :js do
- visit admin_user_path(user)
-
- click_action_in_user_dropdown(user.id, 'Block')
-
- expect(page).to have_content('Block user')
- expect(page).to have_content('You can always unblock their account, their data will remain intact.')
-
- find('.modal-footer button', text: 'Block').click
-
- wait_for_requests
-
- expect(page).to have_content('Successfully blocked')
-
- click_action_in_user_dropdown(user.id, 'Unblock')
-
- expect(page).to have_content('Unblock user')
- expect(page).to have_content('You can always block their account again if needed.')
-
- find('.modal-footer button', text: 'Unblock').click
-
- expect(page).to have_content('Successfully unblocked')
-
- click_user_dropdown_toggle(user.id)
- expect(page).to have_content('Block')
- end
- end
-
- context 'when deactivating/re-activating the user' do
- it 'shows confirmation and allows deactivating/re-activating', :js do
- visit admin_user_path(user)
-
- click_action_in_user_dropdown(user.id, 'Deactivate')
-
- expect(page).to have_content('Deactivate user')
- expect(page).to have_content('You can always re-activate their account, their data will remain intact.')
-
- find('.modal-footer button', text: 'Deactivate').click
-
- wait_for_requests
-
- expect(page).to have_content('Successfully deactivated')
-
- click_action_in_user_dropdown(user.id, 'Activate')
-
- expect(page).to have_content('Activate user')
- expect(page).to have_content('You can always deactivate their account again if needed.')
-
- find('.modal-footer button', text: 'Activate').click
-
- wait_for_requests
-
- expect(page).to have_content('Successfully activated')
-
- click_user_dropdown_toggle(user.id)
- expect(page).to have_content('Deactivate')
- end
- end
-
- context 'when user is the sole owner of a group' do
- let_it_be(:group) { create(:group) }
- let_it_be(:user_sole_owner_of_group) { create(:user) }
-
- before do
- group.add_owner(user_sole_owner_of_group)
- end
-
- it 'shows `Delete user and contributions` action but not `Delete user` action', :js do
- visit admin_user_path(user_sole_owner_of_group)
-
- click_user_dropdown_toggle(user_sole_owner_of_group.id)
-
- expect(page).to have_button('Delete user and contributions')
- expect(page).not_to have_button('Delete user', exact: true)
- end
-
- it 'allows user to be deleted by using the `Delete user and contributions` action', :js do
- visit admin_user_path(user_sole_owner_of_group)
-
- click_action_in_user_dropdown(user_sole_owner_of_group.id, 'Delete user and contributions')
-
- within_modal do
- fill_in('username', with: user_sole_owner_of_group.name)
- click_button('Delete user and contributions')
- end
-
- wait_for_requests
-
- expect(page).to have_content('The user is being deleted.')
- end
- end
-
- context 'when a user is locked', time_travel_to: '2020-02-02 10:30:45 -0700' do
- let_it_be(:locked_user) { create(:user, locked_at: DateTime.parse('2020-02-02 10:30:00 -0700')) }
-
- before do
- visit admin_user_path(locked_user)
- end
-
- it "displays `(Locked)` next to user's name" do
- expect(page).to have_content("#{locked_user.name} (Locked)")
- end
-
- it 'allows a user to be unlocked from the `User administration dropdown', :js do
- accept_gl_confirm("Unlock user #{locked_user.name}?", button_text: 'Unlock') do
- click_action_in_user_dropdown(locked_user.id, 'Unlock')
- end
-
- expect(page).not_to have_content("#{locked_user.name} (Locked)")
- end
- end
-
- describe 'Impersonation' do
- let_it_be(:another_user) { create(:user) }
-
- context 'before impersonating' do
- subject { visit admin_user_path(user_to_visit) }
-
- let_it_be(:user_to_visit) { another_user }
-
- shared_examples "user that cannot be impersonated" do
- it 'disables impersonate button' do
- subject
-
- impersonate_btn = find_by_testid('impersonate-user-link')
-
- expect(impersonate_btn).not_to be_nil
- expect(impersonate_btn['disabled']).not_to be_nil
- end
-
- it "shows tooltip with correct error message" do
- subject
-
- expect(find("span[title='#{impersonation_error_msg}']")).not_to be_nil
- end
- end
-
- context 'for other users' do
- it 'shows impersonate button for other users' do
- subject
-
- expect(page).to have_content('Impersonate')
- impersonate_btn = find_by_testid('impersonate-user-link')
- expect(impersonate_btn['disabled']).to be_nil
- end
- end
-
- context 'for admin itself' do
- let(:user_to_visit) { current_user }
-
- it 'does not show impersonate button for admin itself' do
- subject
-
- expect(page).not_to have_content('Impersonate')
- end
- end
-
- context 'for blocked user' do
- let_it_be(:blocked_user) { create(:user, :blocked) }
- let(:user_to_visit) { blocked_user }
- let(:impersonation_error_msg) { _('You cannot impersonate a blocked user') }
-
- it_behaves_like "user that cannot be impersonated"
- end
-
- context 'for user with expired password' do
- let(:user_to_visit) do
- another_user.update!(password_expires_at: Time.zone.now - 5.minutes)
- another_user
- end
-
- let(:impersonation_error_msg) { _("You cannot impersonate a user with an expired password") }
-
- it_behaves_like "user that cannot be impersonated"
- end
-
- context 'for internal user' do
- let_it_be(:internal_user) { create(:user, :bot) }
- let(:user_to_visit) { internal_user }
- let(:impersonation_error_msg) { _("You cannot impersonate an internal user") }
-
- it_behaves_like "user that cannot be impersonated"
- end
-
- context 'for locked user' do
- let_it_be(:locked_user) { create(:user, :locked) }
- let(:user_to_visit) { locked_user }
- let(:impersonation_error_msg) { _("You cannot impersonate a user who cannot log in") }
-
- it_behaves_like "user that cannot be impersonated"
- end
-
- context 'when already impersonating another user' do
- let_it_be(:admin_user) { create(:user, :admin) }
- let(:impersonation_error_msg) { _("You are already impersonating another user") }
-
- subject do
- visit admin_user_path(admin_user)
- click_link 'Impersonate'
- visit admin_user_path(another_user)
- end
-
- it_behaves_like "user that cannot be impersonated"
- end
-
- context 'when impersonation is disabled' do
- before do
- stub_config_setting(impersonation_enabled: false)
- end
-
- it 'does not show impersonate button' do
- subject
-
- expect(page).not_to have_content('Impersonate')
- end
- end
- end
-
- context 'when impersonating' do
- subject { click_link 'Impersonate' }
-
- before do
- visit admin_user_path(another_user)
- end
-
- it 'logs in as the user when impersonate is clicked', :js do
- subject
-
- expect(page).to have_button("#{another_user.name} user’s menu")
- end
-
- it 'sees impersonation log out icon', :js do
- subject
-
- icon = first('[data-testid="incognito-icon"]')
- expect(icon).not_to be nil
- end
-
- context 'when viewing the confirm email warning', :js do
- before do
- stub_application_setting_enum('email_confirmation_setting', 'soft')
- end
-
- let_it_be(:another_user) { create(:user, :unconfirmed) }
- let(:warning_alert) { page.find(:css, '[data-testid="alert-warning"]') }
- let(:expected_styling) { { 'pointer-events' => 'none', 'cursor' => 'default' } }
-
- context 'with an email that does not contain HTML' do
- before do
- subject
- end
-
- it 'displays the warning alert including the email' do
- expect(warning_alert.text).to include("Please check your email (#{another_user.email}) to verify")
- end
- end
-
- context 'with an email that contains HTML' do
- let(:malicious_email) { "malicious@test.com<form><input/title='<script>alert(document.domain)</script>'>" }
- let(:another_user) { create(:user, confirmed_at: nil, unconfirmed_email: malicious_email) }
-
- before do
- subject
- end
-
- it 'displays the impersonation alert, excludes email, and disables links' do
- expect(warning_alert.text).to include("check your email (#{another_user.unconfirmed_email}) to verify")
- end
- end
- end
- end
-
- context 'ending impersonation', :js do
- subject { click_on 'Stop impersonating' }
-
- before do
- visit admin_user_path(another_user)
- click_link 'Impersonate'
- end
-
- it 'logs out of impersonated user back to original user' do
- subject
-
- expect(page).to have_button("#{current_user.name} user’s menu")
- end
-
- it 'is redirected back to the impersonated users page in the admin after stopping' do
- subject
-
- expect(page).to have_current_path("/admin/users/#{another_user.username}", ignore_query: true)
- end
-
- context 'a user with an expired password' do
- before do
- another_user.update!(password_expires_at: Time.zone.now - 5.minutes)
- end
-
- it 'is redirected back to the impersonated users page in the admin after stopping' do
- subject
-
- expect(page).to have_current_path("/admin/users/#{another_user.username}", ignore_query: true)
- end
- end
- end
- end
-
- describe 'Two-factor Authentication status' do
- it 'shows when enabled' do
- user.update!(otp_required_for_login: true)
-
- visit admin_user_path(user)
-
- expect_two_factor_status('Enabled')
- end
-
- it 'shows when disabled' do
- user.update!(otp_required_for_login: false)
-
- visit admin_user_path(user)
-
- expect_two_factor_status('Disabled')
- end
-
- def expect_two_factor_status(status)
- page.within('.two-factor-status') do
- expect(page).to have_content(status)
- end
- end
- end
-
- describe 'Email verification status' do
- let_it_be(:secondary_email) do
- create :email, email: 'secondary@example.com', user: user
- end
-
- it 'displays the correct status for an unverified email address', :aggregate_failures do
- user.update!(confirmed_at: nil, unconfirmed_email: user.email)
- visit admin_user_path(user)
-
- expect(page).to have_content("#{user.email} Unverified")
- expect(page).to have_content("#{secondary_email.email} Unverified")
- end
-
- it 'displays the correct status for a verified email address' do
- visit admin_user_path(user)
- expect(page).to have_content("#{user.email} Verified")
-
- secondary_email.confirm
- expect(secondary_email.confirmed?).to be_truthy
-
- visit admin_user_path(user)
- expect(page).to have_content("#{secondary_email.email} Verified")
- end
- end
-
- describe 'show user identities' do
- it 'shows user identities', :aggregate_failures do
- visit admin_user_identities_path(user)
-
- expect(page).to have_content(user.name)
- expect(page).to have_content('twitter')
- end
- end
-
- describe 'update user identities' do
- before do
- allow(Gitlab::Auth::OAuth::Provider).to receive(:providers).and_return([:twitter, :twitter_updated])
- end
-
- it 'modifies twitter identity', :aggregate_failures do
- visit admin_user_identities_path(user)
-
- find('.table').find(:link, 'Edit').click
- fill_in 'identity_extern_uid', with: '654321'
- select 'twitter_updated', from: 'identity_provider'
- click_button 'Save changes'
-
- expect(page).to have_content(user.name)
- expect(page).to have_content('twitter_updated')
- expect(page).to have_content('654321')
- end
- end
-
- describe 'remove users secondary email', :js do
- let_it_be(:secondary_email) do
- create :email, email: 'secondary@example.com', user: user
- end
-
- it do
- visit admin_user_path(user.username)
-
- expect(page).to have_content("Secondary email: #{secondary_email.email}")
-
- accept_gl_confirm { find("#remove_email_#{secondary_email.id}").click }
-
- expect(page).not_to have_content(secondary_email.email)
- end
- end
-
- describe 'remove user with identities' do
- it 'removes user with twitter identity', :aggregate_failures do
- visit admin_user_identities_path(user)
-
- click_link 'Delete'
-
- expect(page).to have_content(user.name)
- expect(page).not_to have_content('twitter')
- end
- end
-
- describe 'show user keys', :js do
- it do
- key1 = create(:key, user: user, title: 'ssh-rsa Key1')
- key2 = create(:key, user: user, title: 'ssh-rsa Key2')
-
- visit admin_user_path(user)
-
- click_link 'SSH keys'
-
- expect(page).to have_content(key1.title)
- expect(page).to have_content(key2.title)
-
- click_link key2.title
-
- expect(page).to have_content(key2.title)
- expect(page).to have_content(key2.key)
-
- click_button 'Delete'
-
- page.within('.modal') do
- page.click_button('Delete')
- end
-
- expect(page).not_to have_content(key2.title)
- end
- end
-
- describe 'show user attributes' do
- it 'has expected attributes', :aggregate_failures do
- visit admin_user_path(user)
-
- expect(page).to have_content 'Account'
- expect(page).to have_content 'Personal projects limit'
- end
- end
- end
-
- describe 'GET /admin/users', :js do
- context 'user pending approval' do
- it 'shows user info', :aggregate_failures do
- user = create(:user, :blocked_pending_approval)
-
- visit admin_users_path
- click_link 'Pending approval'
- click_link user.name
-
- expect(page).to have_content(user.name)
- expect(page).to have_content('Pending approval')
-
- click_user_dropdown_toggle(user.id)
-
- expect(page).to have_button('Approve')
- expect(page).to have_button('Reject')
- end
- end
- end
-
- context 'when user has an unconfirmed email', :js do
- # Email address contains HTML to ensure email address is displayed in an HTML safe way.
- let_it_be(:unconfirmed_email) { "#{generate(:email)}<h2>testing<img/src=http://localhost:8000/test.png>" }
- let_it_be(:unconfirmed_user) { create(:user, :unconfirmed, unconfirmed_email: unconfirmed_email) }
-
- where(:path_helper) do
- [
- [-> (user) { admin_user_path(user) }],
- [-> (user) { projects_admin_user_path(user) }],
- [-> (user) { keys_admin_user_path(user) }],
- [-> (user) { admin_user_identities_path(user) }],
- [-> (user) { admin_user_impersonation_tokens_path(user) }]
- ]
- end
-
- with_them do
- it "allows an admin to force confirmation of the user's email", :aggregate_failures do
- visit path_helper.call(unconfirmed_user)
-
- click_button 'Confirm user'
-
- within_modal do
- expect(page).to have_content("Confirm user #{unconfirmed_user.name}?")
- expect(page).to have_content(
- "This user has an unconfirmed email address (#{unconfirmed_email}). You may force a confirmation."
- )
-
- click_button 'Confirm user'
- end
-
- expect(page).to have_content('Successfully confirmed')
- expect(page).not_to have_button('Confirm user')
- end
- end
- end
-end
diff --git a/spec/features/admin/users/users_spec.rb b/spec/features/admin/users/users_spec.rb
index 4e988674858..20cedda626b 100644
--- a/spec/features/admin/users/users_spec.rb
+++ b/spec/features/admin/users/users_spec.rb
@@ -12,7 +12,7 @@ RSpec.describe 'Admin::Users', feature_category: :user_management do
before do
sign_in(current_user)
- gitlab_enable_admin_mode_sign_in(current_user)
+ enable_admin_mode!(current_user)
end
describe 'GET /admin/users', :js do
@@ -381,6 +381,24 @@ RSpec.describe 'Admin::Users', feature_category: :user_management do
expect(find_by_testid("user-group-count-#{current_user.id}").text).to eq("2")
end
end
+
+ context 'user pending approval' do
+ it 'shows user info', :aggregate_failures do
+ user = create(:user, :blocked_pending_approval)
+
+ visit admin_users_path
+ click_link 'Pending approval'
+ click_link user.name
+
+ expect(page).to have_content(user.name)
+ expect(page).to have_content('Pending approval')
+
+ click_user_dropdown_toggle(user.id)
+
+ expect(page).to have_button('Approve')
+ expect(page).to have_button('Reject')
+ end
+ end
end
describe 'GET /admin/users/new' do