diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2019-09-26 12:06:00 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2019-09-26 12:06:00 +0000 |
commit | 5707f305f4b961e24369fcdaecf0b8ce1c34bad8 (patch) | |
tree | 3b291653b83b3e6c2bffc77c54527fbe6f6373be /spec | |
parent | 759cd6c2985088d187ed519f2a881c2c690b34ec (diff) | |
download | gitlab-ce-5707f305f4b961e24369fcdaecf0b8ce1c34bad8.tar.gz |
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'spec')
-rw-r--r-- | spec/controllers/admin/sessions_controller_spec.rb | 98 | ||||
-rw-r--r-- | spec/controllers/application_controller_spec.rb | 44 | ||||
-rw-r--r-- | spec/controllers/concerns/enforces_admin_authentication_spec.rb | 82 | ||||
-rw-r--r-- | spec/controllers/health_controller_spec.rb | 5 | ||||
-rw-r--r-- | spec/factories/services.rb | 2 | ||||
-rw-r--r-- | spec/features/admin/admin_settings_spec.rb | 707 | ||||
-rw-r--r-- | spec/frontend/jobs/store/utils_spec.js | 125 | ||||
-rw-r--r-- | spec/frontend/releases/mock_data.js | 2 | ||||
-rw-r--r-- | spec/helpers/nav_helper_spec.rb | 50 | ||||
-rw-r--r-- | spec/lib/gitlab/auth/current_user_mode_spec.rb | 159 | ||||
-rw-r--r-- | spec/lib/gitlab/health_checks/simple_check_shared.rb | 5 | ||||
-rw-r--r-- | spec/requests/api/helpers_spec.rb | 2 | ||||
-rw-r--r-- | spec/serializers/build_action_entity_spec.rb | 7 | ||||
-rw-r--r-- | spec/spec_helper.rb | 19 | ||||
-rw-r--r-- | spec/support/helpers/admin_mode_helpers.rb | 16 | ||||
-rw-r--r-- | spec/support/helpers/login_helpers.rb | 8 | ||||
-rw-r--r-- | spec/support/shared_contexts/session_shared_context.rb | 15 | ||||
-rw-r--r-- | spec/views/admin/sessions/new.html.haml_spec.rb | 29 |
18 files changed, 1033 insertions, 342 deletions
diff --git a/spec/controllers/admin/sessions_controller_spec.rb b/spec/controllers/admin/sessions_controller_spec.rb new file mode 100644 index 00000000000..c1cb57c0b9d --- /dev/null +++ b/spec/controllers/admin/sessions_controller_spec.rb @@ -0,0 +1,98 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Admin::SessionsController, :do_not_mock_admin_mode do + include_context 'custom session' + + let(:user) { create(:user) } + + before do + sign_in(user) + end + + describe '#new' do + context 'for regular users' do + it 'shows error page' do + get :new + + expect(response).to have_gitlab_http_status(:not_found) + expect(controller.send(:current_user_mode).admin_mode?).to be(false) + end + end + + context 'for admin users' do + let(:user) { create(:admin) } + + it 'renders a password form' do + get :new + + expect(response).to render_template :new + expect(controller.send(:current_user_mode).admin_mode?).to be(false) + end + end + end + + describe '#create' do + context 'for regular users' do + it 'shows error page' do + post :create + + expect(response).to have_gitlab_http_status(:not_found) + expect(controller.send(:current_user_mode).admin_mode?).to be(false) + end + end + + context 'for admin users' do + let(:user) { create(:admin) } + + it 'sets admin mode with a valid password' do + expect(controller.send(:current_user_mode).admin_mode?).to be(false) + + controller.store_location_for(:redirect, admin_root_path) + post :create, params: { password: user.password } + + expect(response).to redirect_to admin_root_path + expect(controller.send(:current_user_mode).admin_mode?).to be(true) + end + + it 'fails with an invalid password' do + expect(controller.send(:current_user_mode).admin_mode?).to be(false) + + controller.store_location_for(:redirect, admin_root_path) + + post :create, params: { password: '' } + + expect(response).to render_template :new + expect(controller.send(:current_user_mode).admin_mode?).to be(false) + end + end + end + + describe '#destroy' do + context 'for regular users' do + it 'shows error page' do + get :destroy + + expect(response).to have_gitlab_http_status(404) + expect(controller.send(:current_user_mode).admin_mode?).to be(false) + end + end + + context 'for admin users' do + let(:user) { create(:admin) } + + it 'disables admin mode and redirects to main page' do + expect(controller.send(:current_user_mode).admin_mode?).to be(false) + post :create, params: { password: user.password } + expect(controller.send(:current_user_mode).admin_mode?).to be(true) + + get :destroy + + expect(response).to have_gitlab_http_status(:found) + expect(response).to redirect_to(root_path) + expect(controller.send(:current_user_mode).admin_mode?).to be(false) + end + end + end +end diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb index 5ef8a15d702..8c3642fb047 100644 --- a/spec/controllers/application_controller_spec.rb +++ b/spec/controllers/application_controller_spec.rb @@ -777,4 +777,48 @@ describe ApplicationController do end end end + + describe '#current_user_mode', :do_not_mock_admin_mode do + include_context 'custom session' + + controller(described_class) do + def index + render html: 'authenticated' + end + end + + before do + allow(ActiveSession).to receive(:list_sessions).with(user).and_return([session]) + + sign_in(user) + get :index + end + + context 'with a regular user' do + it 'admin mode is not set' do + expect(response).to have_gitlab_http_status(:ok) + expect(Gitlab::Auth::CurrentUserMode.new(user).admin_mode?).to be(false) + end + end + + context 'with an admin user' do + let(:user) { create(:admin) } + + it 'admin mode is not set' do + expect(response).to have_gitlab_http_status(:ok) + expect(Gitlab::Auth::CurrentUserMode.new(user).admin_mode?).to be(false) + end + + context 'that re-authenticated' do + before do + Gitlab::Auth::CurrentUserMode.new(user).enable_admin_mode!(password: user.password) + end + + it 'admin mode is set' do + expect(response).to have_gitlab_http_status(:ok) + expect(Gitlab::Auth::CurrentUserMode.new(user).admin_mode?).to be(true) + end + end + end + end end diff --git a/spec/controllers/concerns/enforces_admin_authentication_spec.rb b/spec/controllers/concerns/enforces_admin_authentication_spec.rb index e6a6702fdea..019a21e8cf0 100644 --- a/spec/controllers/concerns/enforces_admin_authentication_spec.rb +++ b/spec/controllers/concerns/enforces_admin_authentication_spec.rb @@ -2,7 +2,9 @@ require 'spec_helper' -describe EnforcesAdminAuthentication do +describe EnforcesAdminAuthentication, :do_not_mock_admin_mode do + include AdminModeHelper + let(:user) { create(:user) } before do @@ -10,30 +12,86 @@ describe EnforcesAdminAuthentication do end controller(ApplicationController) do - # `described_class` is not available in this context - include EnforcesAdminAuthentication # rubocop:disable RSpec/DescribedClass + include EnforcesAdminAuthentication def index head :ok end end - describe 'authenticate_admin!' do - context 'as an admin' do - let(:user) { create(:admin) } + context 'feature flag :user_mode_in_session is enabled' do + describe 'authenticate_admin!' do + context 'as an admin' do + let(:user) { create(:admin) } - it 'renders ok' do - get :index + it 'renders redirect for re-authentication and does not set admin mode' do + get :index + + expect(response).to redirect_to new_admin_session_path + expect(assigns(:current_user_mode)&.admin_mode?).to be(false) + end + + context 'when admin mode is active' do + before do + enable_admin_mode!(user) + end + + it 'renders ok' do + get :index + + expect(response).to have_gitlab_http_status(200) + end + end + end + + context 'as a user' do + it 'renders a 404' do + get :index + + expect(response).to have_gitlab_http_status(404) + end + + it 'does not set admin mode' do + get :index - expect(response).to have_gitlab_http_status(200) + # check for nil too since on 404, current_user_mode might not be initialized + expect(assigns(:current_user_mode)&.admin_mode?).to be_falsey + end end end + end + + context 'feature flag :user_mode_in_session is disabled' do + before do + stub_feature_flags(user_mode_in_session: false) + end - context 'as a user' do - it 'renders a 404' do + describe 'authenticate_admin!' do + before do get :index + end + + context 'as an admin' do + let(:user) { create(:admin) } + + it 'allows direct access to page' do + expect(response).to have_gitlab_http_status(200) + end + + it 'does not set admin mode' do + expect(assigns(:current_user_mode)&.admin_mode?).to be_falsey + end + end + + context 'as a user' do + it 'renders a 404' do + expect(response).to have_gitlab_http_status(404) + end - expect(response).to have_gitlab_http_status(404) + it 'does not set admin mode' do + # check for nil too since on 404, current_user_mode might not be initialized + expect(assigns(:current_user_mode)&.admin_mode?).to be_falsey + end end end end diff --git a/spec/controllers/health_controller_spec.rb b/spec/controllers/health_controller_spec.rb index e82dcfcdb64..8c44ae4e3de 100644 --- a/spec/controllers/health_controller_spec.rb +++ b/spec/controllers/health_controller_spec.rb @@ -76,10 +76,7 @@ describe HealthController do it 'responds with liveness checks data' do subject - expect(json_response['db_check']['status']).to eq('ok') - expect(json_response['cache_check']['status']).to eq('ok') - expect(json_response['queues_check']['status']).to eq('ok') - expect(json_response['shared_state_check']['status']).to eq('ok') + expect(json_response['status']).to eq('ok') end end diff --git a/spec/factories/services.rb b/spec/factories/services.rb index c4cb3f07fe7..e063b888d77 100644 --- a/spec/factories/services.rb +++ b/spec/factories/services.rb @@ -117,7 +117,7 @@ FactoryBot.define do end # this is for testing storing values inside properties, which is deprecated and will be removed in - # https://gitlab.com/gitlab-org/gitlab-ce/issues/63084 + # https://gitlab.com/gitlab-org/gitlab/issues/29404 trait :without_properties_callback do jira_tracker_data nil issue_tracker_data nil diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index ab58d9fb9d5..e1c9364067a 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -2,450 +2,529 @@ require 'spec_helper' -describe 'Admin updates settings' do +describe 'Admin updates settings', :clean_gitlab_redis_shared_state, :do_not_mock_admin_mode do include StubENV include TermsHelper let(:admin) { create(:admin) } - before do - stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - sign_in(admin) - end - - context 'General page' do + context 'feature flag :user_mode_in_session is enabled' do before do - visit general_admin_application_settings_path + stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') + sign_in(admin) + gitlab_enable_admin_mode_sign_in(admin) end - it 'Change visibility settings' do - page.within('.as-visibility-access') do - choose "application_setting_default_project_visibility_20" - click_button 'Save changes' + context 'General page' do + before do + visit general_admin_application_settings_path end - expect(page).to have_content "Application settings saved successfully" - end + it 'Change visibility settings' do + page.within('.as-visibility-access') do + choose "application_setting_default_project_visibility_20" + click_button 'Save changes' + end - it 'Uncheck all restricted visibility levels' do - page.within('.as-visibility-access') do - find('#application_setting_visibility_level_0').set(false) - find('#application_setting_visibility_level_10').set(false) - find('#application_setting_visibility_level_20').set(false) - click_button 'Save changes' + expect(page).to have_content "Application settings saved successfully" end - expect(page).to have_content "Application settings saved successfully" - expect(find('#application_setting_visibility_level_0')).not_to be_checked - expect(find('#application_setting_visibility_level_10')).not_to be_checked - expect(find('#application_setting_visibility_level_20')).not_to be_checked - end + it 'Uncheck all restricted visibility levels' do + page.within('.as-visibility-access') do + find('#application_setting_visibility_level_0').set(false) + find('#application_setting_visibility_level_10').set(false) + find('#application_setting_visibility_level_20').set(false) + click_button 'Save changes' + end + + expect(page).to have_content "Application settings saved successfully" + expect(find('#application_setting_visibility_level_0')).not_to be_checked + expect(find('#application_setting_visibility_level_10')).not_to be_checked + expect(find('#application_setting_visibility_level_20')).not_to be_checked + end - it 'Modify import sources' do - expect(current_settings.import_sources).not_to be_empty + it 'Modify import sources' do + expect(current_settings.import_sources).not_to be_empty - page.within('.as-visibility-access') do - Gitlab::ImportSources.options.map do |name, _| - uncheck name + page.within('.as-visibility-access') do + Gitlab::ImportSources.options.map do |name, _| + uncheck name + end + + click_button 'Save changes' end - click_button 'Save changes' - end + expect(page).to have_content "Application settings saved successfully" + expect(current_settings.import_sources).to be_empty - expect(page).to have_content "Application settings saved successfully" - expect(current_settings.import_sources).to be_empty + page.within('.as-visibility-access') do + check "Repo by URL" + click_button 'Save changes' + end - page.within('.as-visibility-access') do - check "Repo by URL" - click_button 'Save changes' + expect(page).to have_content "Application settings saved successfully" + expect(current_settings.import_sources).to eq(['git']) end - expect(page).to have_content "Application settings saved successfully" - expect(current_settings.import_sources).to eq(['git']) - end + it 'Change Visibility and Access Controls' do + page.within('.as-visibility-access') do + uncheck 'Project export enabled' + click_button 'Save changes' + end - it 'Change Visibility and Access Controls' do - page.within('.as-visibility-access') do - uncheck 'Project export enabled' - click_button 'Save changes' + expect(current_settings.project_export_enabled).to be_falsey + expect(page).to have_content "Application settings saved successfully" end - expect(current_settings.project_export_enabled).to be_falsey - expect(page).to have_content "Application settings saved successfully" - end + it 'Change Keys settings' do + page.within('.as-visibility-access') do + select 'Are forbidden', from: 'RSA SSH keys' + select 'Are allowed', from: 'DSA SSH keys' + select 'Must be at least 384 bits', from: 'ECDSA SSH keys' + select 'Are forbidden', from: 'ED25519 SSH keys' + click_on 'Save changes' + end - it 'Change Keys settings' do - page.within('.as-visibility-access') do - select 'Are forbidden', from: 'RSA SSH keys' - select 'Are allowed', from: 'DSA SSH keys' - select 'Must be at least 384 bits', from: 'ECDSA SSH keys' - select 'Are forbidden', from: 'ED25519 SSH keys' - click_on 'Save changes' - end + forbidden = ApplicationSetting::FORBIDDEN_KEY_VALUE.to_s - forbidden = ApplicationSetting::FORBIDDEN_KEY_VALUE.to_s + expect(page).to have_content 'Application settings saved successfully' + expect(find_field('RSA SSH keys').value).to eq(forbidden) + expect(find_field('DSA SSH keys').value).to eq('0') + expect(find_field('ECDSA SSH keys').value).to eq('384') + expect(find_field('ED25519 SSH keys').value).to eq(forbidden) + end - expect(page).to have_content 'Application settings saved successfully' - expect(find_field('RSA SSH keys').value).to eq(forbidden) - expect(find_field('DSA SSH keys').value).to eq('0') - expect(find_field('ECDSA SSH keys').value).to eq('384') - expect(find_field('ED25519 SSH keys').value).to eq(forbidden) - end + it 'Change Account and Limit Settings' do + page.within('.as-account-limit') do + uncheck 'Gravatar enabled' + click_button 'Save changes' + end - it 'Change Account and Limit Settings' do - page.within('.as-account-limit') do - uncheck 'Gravatar enabled' - click_button 'Save changes' + expect(current_settings.gravatar_enabled).to be_falsey + expect(page).to have_content "Application settings saved successfully" end - expect(current_settings.gravatar_enabled).to be_falsey - expect(page).to have_content "Application settings saved successfully" - end + it 'Change New users set to external', :js do + user_internal_regex = find('#application_setting_user_default_internal_regex', visible: :all) - it 'Change New users set to external', :js do - user_internal_regex = find('#application_setting_user_default_internal_regex', visible: :all) + expect(user_internal_regex).to be_readonly + expect(user_internal_regex['placeholder']).to eq 'To define internal users, first enable new users set to external' - expect(user_internal_regex).to be_readonly - expect(user_internal_regex['placeholder']).to eq 'To define internal users, first enable new users set to external' + check 'application_setting_user_default_external' - check 'application_setting_user_default_external' + expect(user_internal_regex).not_to be_readonly + expect(user_internal_regex['placeholder']).to eq 'Regex pattern' + end - expect(user_internal_regex).not_to be_readonly - expect(user_internal_regex['placeholder']).to eq 'Regex pattern' - end + it 'Change Sign-in restrictions' do + page.within('.as-signin') do + fill_in 'Home page URL', with: 'https://about.gitlab.com/' + click_button 'Save changes' + end - it 'Change Sign-in restrictions' do - page.within('.as-signin') do - fill_in 'Home page URL', with: 'https://about.gitlab.com/' - click_button 'Save changes' + expect(current_settings.home_page_url).to eq "https://about.gitlab.com/" + expect(page).to have_content "Application settings saved successfully" end - expect(current_settings.home_page_url).to eq "https://about.gitlab.com/" - expect(page).to have_content "Application settings saved successfully" - end + it 'Terms of Service' do + # Already have the admin accept terms, so they don't need to accept in this spec. + _existing_terms = create(:term) + accept_terms(admin) - it 'Terms of Service' do - # Already have the admin accept terms, so they don't need to accept in this spec. - _existing_terms = create(:term) - accept_terms(admin) + page.within('.as-terms') do + check 'Require all users to accept Terms of Service and Privacy Policy when they access GitLab.' + fill_in 'Terms of Service Agreement', with: 'Be nice!' + click_button 'Save changes' + end - page.within('.as-terms') do - check 'Require all users to accept Terms of Service and Privacy Policy when they access GitLab.' - fill_in 'Terms of Service Agreement', with: 'Be nice!' - click_button 'Save changes' + expect(current_settings.enforce_terms).to be(true) + expect(current_settings.terms).to eq 'Be nice!' + expect(page).to have_content 'Application settings saved successfully' end - expect(current_settings.enforce_terms).to be(true) - expect(current_settings.terms).to eq 'Be nice!' - expect(page).to have_content 'Application settings saved successfully' - end + it 'Modify oauth providers' do + expect(current_settings.disabled_oauth_sign_in_sources).to be_empty - it 'Modify oauth providers' do - expect(current_settings.disabled_oauth_sign_in_sources).to be_empty + page.within('.as-signin') do + uncheck 'Google' + click_button 'Save changes' + end - page.within('.as-signin') do - uncheck 'Google' - click_button 'Save changes' - end + expect(page).to have_content "Application settings saved successfully" + expect(current_settings.disabled_oauth_sign_in_sources).to include('google_oauth2') - expect(page).to have_content "Application settings saved successfully" - expect(current_settings.disabled_oauth_sign_in_sources).to include('google_oauth2') + page.within('.as-signin') do + check "Google" + click_button 'Save changes' + end - page.within('.as-signin') do - check "Google" - click_button 'Save changes' + expect(page).to have_content "Application settings saved successfully" + expect(current_settings.disabled_oauth_sign_in_sources).not_to include('google_oauth2') end - expect(page).to have_content "Application settings saved successfully" - expect(current_settings.disabled_oauth_sign_in_sources).not_to include('google_oauth2') - end + it 'Oauth providers do not raise validation errors when saving unrelated changes' do + expect(current_settings.disabled_oauth_sign_in_sources).to be_empty - it 'Oauth providers do not raise validation errors when saving unrelated changes' do - expect(current_settings.disabled_oauth_sign_in_sources).to be_empty + page.within('.as-signin') do + uncheck 'Google' + click_button 'Save changes' + end - page.within('.as-signin') do - uncheck 'Google' - click_button 'Save changes' - end + expect(page).to have_content "Application settings saved successfully" + expect(current_settings.disabled_oauth_sign_in_sources).to include('google_oauth2') - expect(page).to have_content "Application settings saved successfully" - expect(current_settings.disabled_oauth_sign_in_sources).to include('google_oauth2') + # Remove google_oauth2 from the Omniauth strategies + allow(Devise).to receive(:omniauth_providers).and_return([]) - # Remove google_oauth2 from the Omniauth strategies - allow(Devise).to receive(:omniauth_providers).and_return([]) + # Save an unrelated setting + page.within('.as-terms') do + click_button 'Save changes' + end - # Save an unrelated setting - page.within('.as-terms') do - click_button 'Save changes' + expect(page).to have_content "Application settings saved successfully" + expect(current_settings.disabled_oauth_sign_in_sources).to include('google_oauth2') end - expect(page).to have_content "Application settings saved successfully" - expect(current_settings.disabled_oauth_sign_in_sources).to include('google_oauth2') + it 'Configure web terminal' do + page.within('.as-terminal') do + fill_in 'Max session time', with: 15 + click_button 'Save changes' + end + + expect(page).to have_content "Application settings saved successfully" + expect(current_settings.terminal_max_session_time).to eq(15) + end end - it 'Configure web terminal' do - page.within('.as-terminal') do - fill_in 'Max session time', with: 15 - click_button 'Save changes' + context 'Integrations page' do + before do + visit integrations_admin_application_settings_path end - expect(page).to have_content "Application settings saved successfully" - expect(current_settings.terminal_max_session_time).to eq(15) - end - end + it 'Enable hiding third party offers' do + page.within('.as-third-party-offers') do + check 'Do not display offers from third parties within GitLab' + click_button 'Save changes' + end - context 'Integrations page' do - before do - visit integrations_admin_application_settings_path - end + expect(page).to have_content "Application settings saved successfully" + expect(current_settings.hide_third_party_offers).to be true + end + + it 'Change Slack Notifications Service template settings' do + first(:link, 'Service Templates').click + click_link 'Slack notifications' + fill_in 'Webhook', with: 'http://localhost' + fill_in 'Username', with: 'test_user' + fill_in 'service_push_channel', with: '#test_channel' + page.check('Notify only broken pipelines') + page.select 'All branches', from: 'Branches to be notified' + + check_all_events + click_on 'Save' - it 'Enable hiding third party offers' do - page.within('.as-third-party-offers') do - check 'Do not display offers from third parties within GitLab' - click_button 'Save changes' + expect(page).to have_content 'Application settings saved successfully' + + click_link 'Slack notifications' + + page.all('input[type=checkbox]').each do |checkbox| + expect(checkbox).to be_checked + end + expect(find_field('Webhook').value).to eq 'http://localhost' + expect(find_field('Username').value).to eq 'test_user' + expect(find('#service_push_channel').value).to eq '#test_channel' end - expect(page).to have_content "Application settings saved successfully" - expect(current_settings.hide_third_party_offers).to be true + it 'defaults Deployment events to false for chat notification template settings' do + first(:link, 'Service Templates').click + click_link 'Slack notifications' + + expect(find_field('Deployment')).not_to be_checked + end end - it 'Change Slack Notifications Service template settings' do - first(:link, 'Service Templates').click - click_link 'Slack notifications' - fill_in 'Webhook', with: 'http://localhost' - fill_in 'Username', with: 'test_user' - fill_in 'service_push_channel', with: '#test_channel' - page.check('Notify only broken pipelines') - page.select 'All branches', from: 'Branches to be notified' + context 'CI/CD page' do + it 'Change CI/CD settings' do + visit ci_cd_admin_application_settings_path + + page.within('.as-ci-cd') do + check 'Default to Auto DevOps pipeline for all projects' + fill_in 'application_setting_auto_devops_domain', with: 'domain.com' + click_button 'Save changes' + end - check_all_events - click_on 'Save' + expect(current_settings.auto_devops_enabled?).to be true + expect(current_settings.auto_devops_domain).to eq('domain.com') + expect(page).to have_content "Application settings saved successfully" + end + end - expect(page).to have_content 'Application settings saved successfully' + context 'Reporting page' do + it 'Change Spam settings' do + visit reporting_admin_application_settings_path - click_link 'Slack notifications' + page.within('.as-spam') do + check 'Enable reCAPTCHA' + check 'Enable reCAPTCHA for login' + fill_in 'reCAPTCHA Site Key', with: 'key' + fill_in 'reCAPTCHA Private Key', with: 'key' + fill_in 'IPs per user', with: 15 + click_button 'Save changes' + end - page.all('input[type=checkbox]').each do |checkbox| - expect(checkbox).to be_checked + expect(page).to have_content "Application settings saved successfully" + expect(current_settings.recaptcha_enabled).to be true + expect(current_settings.login_recaptcha_protection_enabled).to be true + expect(current_settings.unique_ips_limit_per_user).to eq(15) end - expect(find_field('Webhook').value).to eq 'http://localhost' - expect(find_field('Username').value).to eq 'test_user' - expect(find('#service_push_channel').value).to eq '#test_channel' end - it 'defaults Deployment events to false for chat notification template settings' do - first(:link, 'Service Templates').click - click_link 'Slack notifications' + context 'Metrics and profiling page' do + before do + visit metrics_and_profiling_admin_application_settings_path + end - expect(find_field('Deployment')).not_to be_checked - end - end + it 'Change Influx settings' do + page.within('.as-influx') do + check 'Enable InfluxDB Metrics' + click_button 'Save changes' + end - context 'CI/CD page' do - it 'Change CI/CD settings' do - visit ci_cd_admin_application_settings_path + expect(current_settings.metrics_enabled?).to be true + expect(page).to have_content "Application settings saved successfully" + end + + it 'Change Prometheus settings' do + page.within('.as-prometheus') do + check 'Enable Prometheus Metrics' + click_button 'Save changes' + end - page.within('.as-ci-cd') do - check 'Default to Auto DevOps pipeline for all projects' - fill_in 'application_setting_auto_devops_domain', with: 'domain.com' - click_button 'Save changes' + expect(current_settings.prometheus_metrics_enabled?).to be true + expect(page).to have_content "Application settings saved successfully" end - expect(current_settings.auto_devops_enabled?).to be true - expect(current_settings.auto_devops_domain).to eq('domain.com') - expect(page).to have_content "Application settings saved successfully" - end - end + it 'Change Performance bar settings' do + group = create(:group) + + page.within('.as-performance-bar') do + check 'Enable access to the Performance Bar' + fill_in 'Allowed group', with: group.path + click_on 'Save changes' + end - context 'Reporting page' do - it 'Change Spam settings' do - visit reporting_admin_application_settings_path + expect(page).to have_content "Application settings saved successfully" + expect(find_field('Enable access to the Performance Bar')).to be_checked + expect(find_field('Allowed group').value).to eq group.path - page.within('.as-spam') do - check 'Enable reCAPTCHA' - check 'Enable reCAPTCHA for login' - fill_in 'reCAPTCHA Site Key', with: 'key' - fill_in 'reCAPTCHA Private Key', with: 'key' - fill_in 'IPs per user', with: 15 - click_button 'Save changes' + page.within('.as-performance-bar') do + uncheck 'Enable access to the Performance Bar' + click_on 'Save changes' + end + + expect(page).to have_content 'Application settings saved successfully' + expect(find_field('Enable access to the Performance Bar')).not_to be_checked + expect(find_field('Allowed group').value).to be_nil end - expect(page).to have_content "Application settings saved successfully" - expect(current_settings.recaptcha_enabled).to be true - expect(current_settings.login_recaptcha_protection_enabled).to be true - expect(current_settings.unique_ips_limit_per_user).to eq(15) - end - end + it 'loads usage ping payload on click', :js do + expect(page).to have_button 'Preview payload' - context 'Metrics and profiling page' do - before do - visit metrics_and_profiling_admin_application_settings_path - end + find('.js-usage-ping-payload-trigger').click - it 'Change Influx settings' do - page.within('.as-influx') do - check 'Enable InfluxDB Metrics' - click_button 'Save changes' + expect(page).to have_selector '.js-usage-ping-payload' + expect(page).to have_button 'Hide payload' end + end + + context 'Network page' do + it 'Changes Outbound requests settings' do + visit network_admin_application_settings_path - expect(current_settings.metrics_enabled?).to be true - expect(page).to have_content "Application settings saved successfully" + page.within('.as-outbound') do + check 'Allow requests to the local network from web hooks and services' + # Enabled by default + uncheck 'Allow requests to the local network from system hooks' + # Enabled by default + uncheck 'Enforce DNS rebinding attack protection' + click_button 'Save changes' + end + + expect(page).to have_content "Application settings saved successfully" + expect(current_settings.allow_local_requests_from_web_hooks_and_services).to be true + expect(current_settings.allow_local_requests_from_system_hooks).to be false + expect(current_settings.dns_rebinding_protection_enabled).to be false + end end - it 'Change Prometheus settings' do - page.within('.as-prometheus') do - check 'Enable Prometheus Metrics' - click_button 'Save changes' + context 'Preferences page' do + before do + visit preferences_admin_application_settings_path end - expect(current_settings.prometheus_metrics_enabled?).to be true - expect(page).to have_content "Application settings saved successfully" - end + it 'Change Help page' do + new_support_url = 'http://example.com/help' - it 'Change Performance bar settings' do - group = create(:group) + page.within('.as-help-page') do + fill_in 'Help page text', with: 'Example text' + check 'Hide marketing-related entries from help' + fill_in 'Support page URL', with: new_support_url + click_button 'Save changes' + end - page.within('.as-performance-bar') do - check 'Enable access to the Performance Bar' - fill_in 'Allowed group', with: group.path - click_on 'Save changes' + expect(current_settings.help_page_text).to eq "Example text" + expect(current_settings.help_page_hide_commercial_content).to be_truthy + expect(current_settings.help_page_support_url).to eq new_support_url + expect(page).to have_content "Application settings saved successfully" end - expect(page).to have_content "Application settings saved successfully" - expect(find_field('Enable access to the Performance Bar')).to be_checked - expect(find_field('Allowed group').value).to eq group.path + it 'Change Pages settings' do + page.within('.as-pages') do + fill_in 'Maximum size of pages (MB)', with: 15 + check 'Require users to prove ownership of custom domains' + click_button 'Save changes' + end - page.within('.as-performance-bar') do - uncheck 'Enable access to the Performance Bar' - click_on 'Save changes' + expect(current_settings.max_pages_size).to eq 15 + expect(current_settings.pages_domain_verification_enabled?).to be_truthy + expect(page).to have_content "Application settings saved successfully" end - expect(page).to have_content 'Application settings saved successfully' - expect(find_field('Enable access to the Performance Bar')).not_to be_checked - expect(find_field('Allowed group').value).to be_nil - end + it 'Change Real-time features settings' do + page.within('.as-realtime') do + fill_in 'Polling interval multiplier', with: 5.0 + click_button 'Save changes' + end - it 'loads usage ping payload on click', :js do - expect(page).to have_button 'Preview payload' + expect(current_settings.polling_interval_multiplier).to eq 5.0 + expect(page).to have_content "Application settings saved successfully" + end - find('.js-usage-ping-payload-trigger').click + it 'shows an error when validation fails' do + page.within('.as-realtime') do + fill_in 'Polling interval multiplier', with: -1.0 + click_button 'Save changes' + end - expect(page).to have_selector '.js-usage-ping-payload' - expect(page).to have_button 'Hide payload' - end - end + expect(current_settings.polling_interval_multiplier).not_to eq(-1.0) + expect(page) + .to have_content "The form contains the following error: Polling interval multiplier must be greater than or equal to 0" + end - context 'Network page' do - it 'Changes Outbound requests settings' do - visit network_admin_application_settings_path + it "Change Pages Let's Encrypt settings" do + visit preferences_admin_application_settings_path + page.within('.as-pages') do + fill_in 'Email', with: 'my@test.example.com' + check "I have read and agree to the Let's Encrypt Terms of Service" + click_button 'Save changes' + end - page.within('.as-outbound') do - check 'Allow requests to the local network from web hooks and services' - # Enabled by default - uncheck 'Allow requests to the local network from system hooks' - # Enabled by default - uncheck 'Enforce DNS rebinding attack protection' - click_button 'Save changes' + expect(current_settings.lets_encrypt_notification_email).to eq 'my@test.example.com' + expect(current_settings.lets_encrypt_terms_of_service_accepted).to eq true end - - expect(page).to have_content "Application settings saved successfully" - expect(current_settings.allow_local_requests_from_web_hooks_and_services).to be true - expect(current_settings.allow_local_requests_from_system_hooks).to be false - expect(current_settings.dns_rebinding_protection_enabled).to be false end - end - context 'Preferences page' do - before do - visit preferences_admin_application_settings_path - end + context 'Nav bar' do + it 'Shows default help links in nav' do + default_support_url = 'https://about.gitlab.com/getting-help/' - it 'Change Help page' do - new_support_url = 'http://example.com/help' + visit root_dashboard_path - page.within('.as-help-page') do - fill_in 'Help page text', with: 'Example text' - check 'Hide marketing-related entries from help' - fill_in 'Support page URL', with: new_support_url - click_button 'Save changes' + find('.header-help-dropdown-toggle').click + + page.within '.header-help' do + expect(page).to have_link(text: 'Help', href: help_path) + expect(page).to have_link(text: 'Support', href: default_support_url) + end end - expect(current_settings.help_page_text).to eq "Example text" - expect(current_settings.help_page_hide_commercial_content).to be_truthy - expect(current_settings.help_page_support_url).to eq new_support_url - expect(page).to have_content "Application settings saved successfully" - end + it 'Shows custom support url in nav when set' do + new_support_url = 'http://example.com/help' + stub_application_setting(help_page_support_url: new_support_url) - it 'Change Pages settings' do - page.within('.as-pages') do - fill_in 'Maximum size of pages (MB)', with: 15 - check 'Require users to prove ownership of custom domains' - click_button 'Save changes' - end + visit root_dashboard_path - expect(current_settings.max_pages_size).to eq 15 - expect(current_settings.pages_domain_verification_enabled?).to be_truthy - expect(page).to have_content "Application settings saved successfully" + find('.header-help-dropdown-toggle').click + + page.within '.header-help' do + expect(page).to have_link(text: 'Support', href: new_support_url) + end + end end - it 'Change Real-time features settings' do - page.within('.as-realtime') do - fill_in 'Polling interval multiplier', with: 5.0 - click_button 'Save changes' + context 'when in admin_mode' do + it 'contains link to leave admin mode' do + page.within('.navbar-sub-nav') do + expect(page).to have_link(href: destroy_admin_session_path) + end end - expect(current_settings.polling_interval_multiplier).to eq 5.0 - expect(page).to have_content "Application settings saved successfully" - end + it 'can leave admin mode' do + page.within('.navbar-sub-nav') do + # Select first, link is also included in mobile view list + click_on 'Leave admin mode', match: :first - it 'shows an error when validation fails' do - page.within('.as-realtime') do - fill_in 'Polling interval multiplier', with: -1.0 - click_button 'Save changes' + expect(page).to have_link(href: new_admin_session_path) + end end - expect(current_settings.polling_interval_multiplier).not_to eq(-1.0) - expect(page) - .to have_content "The form contains the following error: Polling interval multiplier must be greater than or equal to 0" + it 'can open pages not in admin scope' do + page.within('.navbar-sub-nav') do + find_all('a', text: 'Projects').first.click + + expect(page).to have_current_path(dashboard_projects_path) + end + end end - it "Change Pages Let's Encrypt settings" do - visit preferences_admin_application_settings_path - page.within('.as-pages') do - fill_in 'Email', with: 'my@test.example.com' - check "I have read and agree to the Let's Encrypt Terms of Service" - click_button 'Save changes' + context 'when not in admin mode' do + before do + page.within('.navbar-sub-nav') do + # Select first, link is also included in mobile view list + click_on 'Leave admin mode', match: :first + end end - expect(current_settings.lets_encrypt_notification_email).to eq 'my@test.example.com' - expect(current_settings.lets_encrypt_terms_of_service_accepted).to eq true - end - end + it 'has no leave admin mode button' do + page.within('.navbar-sub-nav') do + expect(page).not_to have_link(href: destroy_admin_session_path) + end + end - context 'Nav bar' do - it 'Shows default help links in nav' do - default_support_url = 'https://about.gitlab.com/getting-help/' + it 'is necessary to provide credentials again before opening admin settings' do + visit admin_application_settings_path # admin logged out because not in admin_mode - visit root_dashboard_path + expect(page).to have_current_path(new_admin_session_path) + end - find('.header-help-dropdown-toggle').click + it 'can open pages not in admin scope' do + page.within('.navbar-sub-nav') do + find_all('a', text: 'Projects').first.click + end - page.within '.header-help' do - expect(page).to have_link(text: 'Help', href: help_path) - expect(page).to have_link(text: 'Support', href: default_support_url) + expect(page).to have_current_path(dashboard_projects_path) end end + end - it 'Shows custom support url in nav when set' do - new_support_url = 'http://example.com/help' - stub_application_setting(help_page_support_url: new_support_url) + context 'feature flag :user_mode_in_session is disabled' do + before do + stub_feature_flags(user_mode_in_session: false) - visit root_dashboard_path + stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false') - find('.header-help-dropdown-toggle').click + sign_in(admin) + visit admin_application_settings_path + end + + it 'loads admin settings page without redirect for reauthentication' do + expect(current_path).to eq admin_application_settings_path + end - page.within '.header-help' do - expect(page).to have_link(text: 'Support', href: new_support_url) + it 'shows no admin mode buttons in navbar' do + page.within('.navbar-sub-nav') do + expect(page).not_to have_link(href: new_admin_session_path) + expect(page).not_to have_link(href: destroy_admin_session_path) end end end diff --git a/spec/frontend/jobs/store/utils_spec.js b/spec/frontend/jobs/store/utils_spec.js index bb45fcb7435..18f9026b487 100644 --- a/spec/frontend/jobs/store/utils_spec.js +++ b/spec/frontend/jobs/store/utils_spec.js @@ -3,6 +3,8 @@ import { updateIncrementalTrace, parseHeaderLine, parseLine, + addDurationToHeader, + isCollapsibleSection, findOffsetAndRemove, } from '~/jobs/store/utils'; import { @@ -43,6 +45,127 @@ describe('Jobs Store Utils', () => { }); }); + describe('addDurationToHeader', () => { + const duration = { + offset: 106, + content: [], + section: 'prepare-script', + section_duration: '00:03', + }; + + it('adds the section duration to the correct header', () => { + const parsed = [ + { + isClosed: true, + isHeader: true, + line: { + section: 'prepare-script', + content: [{ text: 'foo' }], + }, + lines: [], + }, + { + isClosed: true, + isHeader: true, + line: { + section: 'foo-bar', + content: [{ text: 'foo' }], + }, + lines: [], + }, + ]; + + addDurationToHeader(parsed, duration); + + expect(parsed[0].line.section_duration).toEqual(duration.section_duration); + expect(parsed[1].line.section_duration).toEqual(undefined); + }); + + it('does not add the section duration when the headers do not match', () => { + const parsed = [ + { + isClosed: true, + isHeader: true, + line: { + section: 'bar-foo', + content: [{ text: 'foo' }], + }, + lines: [], + }, + { + isClosed: true, + isHeader: true, + line: { + section: 'foo-bar', + content: [{ text: 'foo' }], + }, + lines: [], + }, + ]; + addDurationToHeader(parsed, duration); + + expect(parsed[0].line.section_duration).toEqual(undefined); + expect(parsed[1].line.section_duration).toEqual(undefined); + }); + + it('does not add when content has no headers', () => { + const parsed = [ + { + section: 'bar-foo', + content: [{ text: 'foo' }], + lineNumber: 1, + }, + { + section: 'foo-bar', + content: [{ text: 'foo' }], + lineNumber: 2, + }, + ]; + + addDurationToHeader(parsed, duration); + + expect(parsed[0].line).toEqual(undefined); + expect(parsed[1].line).toEqual(undefined); + }); + }); + + describe('isCollapsibleSection', () => { + const header = { + isHeader: true, + line: { + section: 'foo', + }, + }; + const line = { + lineNumber: 1, + section: 'foo', + content: [], + }; + + it('returns true when line belongs to the last section', () => { + expect(isCollapsibleSection([header], header, { section: 'foo', content: [] })).toEqual(true); + }); + + it('returns false when last line was not an header', () => { + expect(isCollapsibleSection([line], line, { section: 'bar' })).toEqual(false); + }); + + it('returns false when accumulator is empty', () => { + expect(isCollapsibleSection([], { isHeader: true }, { section: 'bar' })).toEqual(false); + }); + + it('returns false when section_duration is defined', () => { + expect(isCollapsibleSection([header], header, { section_duration: '10:00' })).toEqual(false); + }); + + it('returns false when `section` is not a match', () => { + expect(isCollapsibleSection([header], header, { section: 'bar' })).toEqual(false); + }); + + it('returns false when no parameters are provided', () => { + expect(isCollapsibleSection()).toEqual(false); + }); + }); describe('logLinesParser', () => { let result; @@ -75,7 +198,7 @@ describe('Jobs Store Utils', () => { describe('section duration', () => { it('adds the section information to the header section', () => { - expect(result[1].section_duration).toEqual(utilsMockData[4].section_duration); + expect(result[1].line.section_duration).toEqual(utilsMockData[4].section_duration); }); it('does not add section duration as a line', () => { diff --git a/spec/frontend/releases/mock_data.js b/spec/frontend/releases/mock_data.js index a0885813c7e..aff441e675e 100644 --- a/spec/frontend/releases/mock_data.js +++ b/spec/frontend/releases/mock_data.js @@ -89,7 +89,7 @@ export const release = { id: 2, name: 'my second link', url: - 'https://gitlab.com/gitlab-org/gitlab-ce/-/jobs/artifacts/v11.6.0-rc4/download?job=rspec-mysql+41%2F50', + 'https://gitlab.com/gitlab-org/gitlab-foss/-/jobs/artifacts/v11.6.0-rc4/download?job=rspec-mysql+41%2F50', external: false, }, ], diff --git a/spec/helpers/nav_helper_spec.rb b/spec/helpers/nav_helper_spec.rb index 979d89812f5..ff2be795d87 100644 --- a/spec/helpers/nav_helper_spec.rb +++ b/spec/helpers/nav_helper_spec.rb @@ -1,16 +1,20 @@ require 'spec_helper' -describe NavHelper do +describe NavHelper, :do_not_mock_admin_mode do describe '#header_links' do + include_context 'custom session' + before do - allow(helper).to receive(:session) { {} } + allow(helper).to receive(:session).and_return(session) end context 'when the user is logged in' do - let(:user) { build(:user) } + let(:user) { create(:user) } + let(:current_user_mode) { Gitlab::Auth::CurrentUserMode.new(user) } before do allow(helper).to receive(:current_user).and_return(user) + allow(helper).to receive(:current_user_mode).and_return(current_user_mode) allow(helper).to receive(:can?) { true } end @@ -26,6 +30,46 @@ describe NavHelper do expect(helper.header_links).to include(:admin_impersonation) end + context 'as admin' do + let(:user) { create(:user, :admin) } + + context 'feature flag :user_mode_in_session is enabled' do + it 'does not contain the admin mode link by default' do + expect(helper.header_links).not_to include(:admin_mode) + end + + context 'with admin mode enabled' do + before do + current_user_mode.enable_admin_mode!(password: user.password) + end + + it 'contains the admin mode link' do + expect(helper.header_links).to include(:admin_mode) + end + end + end + + context 'feature flag :user_mode_in_session is disabled' do + before do + stub_feature_flags(user_mode_in_session: false) + end + + it 'does not contain the admin mode link' do + expect(helper.header_links).not_to include(:admin_mode) + end + + context 'with admin mode enabled' do + before do + current_user_mode.enable_admin_mode!(password: user.password) + end + + it 'has no effect on header links' do + expect(helper.header_links).not_to include(:admin_mode) + end + end + end + end + context 'when the user cannot read cross project' do before do allow(helper).to receive(:can?).with(user, :read_cross_project) { false } diff --git a/spec/lib/gitlab/auth/current_user_mode_spec.rb b/spec/lib/gitlab/auth/current_user_mode_spec.rb new file mode 100644 index 00000000000..b93d460cf48 --- /dev/null +++ b/spec/lib/gitlab/auth/current_user_mode_spec.rb @@ -0,0 +1,159 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Gitlab::Auth::CurrentUserMode, :do_not_mock_admin_mode do + include_context 'custom session' + + let(:user) { build(:user) } + + subject { described_class.new(user) } + + before do + allow(ActiveSession).to receive(:list_sessions).with(user).and_return([session]) + end + + describe '#admin_mode?', :request_store do + context 'when the user is a regular user' do + it 'is false by default' do + expect(subject.admin_mode?).to be(false) + end + + it 'cannot be enabled with a valid password' do + subject.enable_admin_mode!(password: user.password) + + expect(subject.admin_mode?).to be(false) + end + + it 'cannot be enabled with an invalid password' do + subject.enable_admin_mode!(password: nil) + + expect(subject.admin_mode?).to be(false) + end + + it 'cannot be enabled with empty params' do + subject.enable_admin_mode! + + expect(subject.admin_mode?).to be(false) + end + + it 'disable has no effect' do + subject.enable_admin_mode! + subject.disable_admin_mode! + + expect(subject.admin_mode?).to be(false) + end + + context 'skipping password validation' do + it 'cannot be enabled with a valid password' do + subject.enable_admin_mode!(password: user.password, skip_password_validation: true) + + expect(subject.admin_mode?).to be(false) + end + + it 'cannot be enabled with an invalid password' do + subject.enable_admin_mode!(skip_password_validation: true) + + expect(subject.admin_mode?).to be(false) + end + end + end + + context 'when the user is an admin' do + let(:user) { build(:user, :admin) } + + it 'is false by default' do + expect(subject.admin_mode?).to be(false) + end + + it 'cannot be enabled with an invalid password' do + subject.enable_admin_mode!(password: nil) + + expect(subject.admin_mode?).to be(false) + end + + it 'can be enabled with a valid password' do + subject.enable_admin_mode!(password: user.password) + + expect(subject.admin_mode?).to be(true) + end + + it 'can be disabled' do + subject.enable_admin_mode!(password: user.password) + subject.disable_admin_mode! + + expect(subject.admin_mode?).to be(false) + end + + it 'will expire in the future' do + subject.enable_admin_mode!(password: user.password) + expect(subject.admin_mode?).to be(true), 'admin mode is not active in the present' + + Timecop.freeze(Gitlab::Auth::CurrentUserMode::MAX_ADMIN_MODE_TIME.from_now) do + # in the future this will be a new request, simulate by clearing the RequestStore + Gitlab::SafeRequestStore.clear! + + expect(subject.admin_mode?).to be(false), 'admin mode did not expire in the future' + end + end + + context 'skipping password validation' do + it 'can be enabled with a valid password' do + subject.enable_admin_mode!(password: user.password, skip_password_validation: true) + + expect(subject.admin_mode?).to be(true) + end + + it 'can be enabled with an invalid password' do + subject.enable_admin_mode!(skip_password_validation: true) + + expect(subject.admin_mode?).to be(true) + end + end + + context 'with two independent sessions' do + let(:another_session) { {} } + let(:another_subject) { described_class.new(user) } + + before do + allow(ActiveSession).to receive(:list_sessions).with(user).and_return([session, another_session]) + end + + it 'can be enabled in one and seen in the other' do + Gitlab::Session.with_session(another_session) do + another_subject.enable_admin_mode!(password: user.password) + end + + expect(subject.admin_mode?).to be(true) + end + end + end + end + + describe '#enable_admin_mode!' do + let(:user) { build(:user, :admin) } + + it 'creates a timestamp in the session' do + subject.enable_admin_mode!(password: user.password) + + expect(session).to include(expected_session_entry(be_within(1.second).of Time.now)) + end + end + + describe '#disable_admin_mode!' do + let(:user) { build(:user, :admin) } + + it 'sets the session timestamp to nil' do + subject.disable_admin_mode! + + expect(session).to include(expected_session_entry(be_nil)) + end + end + + def expected_session_entry(value_matcher) + { + Gitlab::Auth::CurrentUserMode::SESSION_STORE_KEY => a_hash_including( + Gitlab::Auth::CurrentUserMode::ADMIN_MODE_START_TIME_KEY => value_matcher) + } + end +end diff --git a/spec/lib/gitlab/health_checks/simple_check_shared.rb b/spec/lib/gitlab/health_checks/simple_check_shared.rb index e2643458aca..b4a8a4e6ab6 100644 --- a/spec/lib/gitlab/health_checks/simple_check_shared.rb +++ b/spec/lib/gitlab/health_checks/simple_check_shared.rb @@ -58,9 +58,4 @@ shared_context 'simple_check' do |metrics_prefix, check_name, success_result| it { is_expected.to have_attributes(success: false, message: "#{described_class.human_name} check timed out") } end end - - describe '#liveness' do - subject { described_class.readiness } - it { is_expected.to eq(Gitlab::HealthChecks::Result.new(true)) } - end end diff --git a/spec/requests/api/helpers_spec.rb b/spec/requests/api/helpers_spec.rb index 29dc84c1924..a1a007811fe 100644 --- a/spec/requests/api/helpers_spec.rb +++ b/spec/requests/api/helpers_spec.rb @@ -343,6 +343,8 @@ describe API::Helpers do end context 'sudo' do + include_context 'custom session' + shared_examples 'successful sudo' do it 'sets current_user' do expect(current_user).to eq(user) diff --git a/spec/serializers/build_action_entity_spec.rb b/spec/serializers/build_action_entity_spec.rb index ea88951ebc6..4d335e8fb77 100644 --- a/spec/serializers/build_action_entity_spec.rb +++ b/spec/serializers/build_action_entity_spec.rb @@ -3,9 +3,14 @@ require 'spec_helper' describe BuildActionEntity do let(:job) { create(:ci_build, name: 'test_job') } let(:request) { double('request') } + let(:user) { create(:user) } let(:entity) do - described_class.new(job, request: spy('request')) + described_class.new(job, request: request) + end + + before do + allow(request).to receive(:current_user).and_return(user) end describe '#as_json' do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 18bfe5a2be7..364c033900f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -160,6 +160,25 @@ RSpec.configure do |config| allow(Gitlab::Git::KeepAround).to receive(:execute) Gitlab::ThreadMemoryCache.cache_backend.clear + + # Temporary patch to force admin mode to be active by default in tests when + # using the feature flag :user_mode_in_session, since this will require + # modifying a significant number of specs to test both states for admin + # mode enabled / disabled. + # + # See https://gitlab.com/gitlab-org/gitlab/issues/31511 + # See gitlab/spec/support/helpers/admin_mode_helpers.rb + # + # If it is required to have the real behaviour that an admin is signed in + # with normal user mode and needs to switch to admin mode, it is possible to + # mark such tests with the `do_not_mock_admin_mode` metadata tag, e.g: + # + # context 'some test with normal user mode', :do_not_mock_admin_mode do ... end + unless example.metadata[:do_not_mock_admin_mode] + allow_any_instance_of(Gitlab::Auth::CurrentUserMode).to receive(:admin_mode?) do |current_user_mode| + current_user_mode.send(:user)&.admin? + end + end end config.around(:example, :quarantine) do |example| diff --git a/spec/support/helpers/admin_mode_helpers.rb b/spec/support/helpers/admin_mode_helpers.rb new file mode 100644 index 00000000000..de8ffe40536 --- /dev/null +++ b/spec/support/helpers/admin_mode_helpers.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +# Helper for enabling admin mode in tests + +module AdminModeHelper + # Users are logged in by default in user mode and have to switch to admin + # mode for accessing any administrative functionality. This helper lets a user + # be in admin mode without requiring a second authentication step (provided + # the user is an admin) + def enable_admin_mode!(user) + fake_user_mode = instance_double(Gitlab::Auth::CurrentUserMode) + + allow(Gitlab::Auth::CurrentUserMode).to receive(:new).with(user).and_return(fake_user_mode) + allow(fake_user_mode).to receive(:admin_mode?).and_return(user&.admin?) + end +end diff --git a/spec/support/helpers/login_helpers.rb b/spec/support/helpers/login_helpers.rb index 140ad173d38..94e23f08f5d 100644 --- a/spec/support/helpers/login_helpers.rb +++ b/spec/support/helpers/login_helpers.rb @@ -48,6 +48,14 @@ module LoginHelpers @current_user = user end + def gitlab_enable_admin_mode_sign_in(user) + visit new_admin_session_path + + fill_in 'password', with: user.password + + click_button 'Enter admin mode' + end + def gitlab_sign_in_via(provider, user, uid, saml_response = nil) mock_auth_hash_with_saml_xml(provider, uid, user.email, saml_response) visit new_user_session_path diff --git a/spec/support/shared_contexts/session_shared_context.rb b/spec/support/shared_contexts/session_shared_context.rb new file mode 100644 index 00000000000..86c145a8360 --- /dev/null +++ b/spec/support/shared_contexts/session_shared_context.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# the session is empty by default; you can overwrite it by defining your own +# let(:session) variable +# we do not use a parameter such as |session| because it does not play nice +# with let variables +shared_context 'custom session' do + let!(:session) { {} } + + around do |example| + Gitlab::Session.with_session(session) do + example.run + end + end +end diff --git a/spec/views/admin/sessions/new.html.haml_spec.rb b/spec/views/admin/sessions/new.html.haml_spec.rb new file mode 100644 index 00000000000..eb431a0b6de --- /dev/null +++ b/spec/views/admin/sessions/new.html.haml_spec.rb @@ -0,0 +1,29 @@ +require 'spec_helper' + +describe 'admin/sessions/new.html.haml' do + context 'admin has password set' do + before do + allow(view).to receive(:password_authentication_enabled_for_web?).and_return(true) + end + + it "shows enter password form" do + render + + expect(rendered).to have_css('#login-pane.active') + expect(rendered).to have_selector('input[name="password"]') + end + end + + context 'admin has no password set' do + before do + allow(view).to receive(:password_authentication_enabled_for_web?).and_return(false) + end + + it "warns authentication not possible" do + render + + expect(rendered).not_to have_css('#login-pane') + expect(rendered).to have_content 'No authentication methods configured' + end + end +end |