summaryrefslogtreecommitdiff
path: root/spec
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-09-26 12:06:00 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-09-26 12:06:00 +0000
commit5707f305f4b961e24369fcdaecf0b8ce1c34bad8 (patch)
tree3b291653b83b3e6c2bffc77c54527fbe6f6373be /spec
parent759cd6c2985088d187ed519f2a881c2c690b34ec (diff)
downloadgitlab-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.rb98
-rw-r--r--spec/controllers/application_controller_spec.rb44
-rw-r--r--spec/controllers/concerns/enforces_admin_authentication_spec.rb82
-rw-r--r--spec/controllers/health_controller_spec.rb5
-rw-r--r--spec/factories/services.rb2
-rw-r--r--spec/features/admin/admin_settings_spec.rb707
-rw-r--r--spec/frontend/jobs/store/utils_spec.js125
-rw-r--r--spec/frontend/releases/mock_data.js2
-rw-r--r--spec/helpers/nav_helper_spec.rb50
-rw-r--r--spec/lib/gitlab/auth/current_user_mode_spec.rb159
-rw-r--r--spec/lib/gitlab/health_checks/simple_check_shared.rb5
-rw-r--r--spec/requests/api/helpers_spec.rb2
-rw-r--r--spec/serializers/build_action_entity_spec.rb7
-rw-r--r--spec/spec_helper.rb19
-rw-r--r--spec/support/helpers/admin_mode_helpers.rb16
-rw-r--r--spec/support/helpers/login_helpers.rb8
-rw-r--r--spec/support/shared_contexts/session_shared_context.rb15
-rw-r--r--spec/views/admin/sessions/new.html.haml_spec.rb29
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