diff options
Diffstat (limited to 'spec/controllers/admin')
7 files changed, 262 insertions, 55 deletions
diff --git a/spec/controllers/admin/cohorts_controller_spec.rb b/spec/controllers/admin/cohorts_controller_spec.rb new file mode 100644 index 00000000000..9eb2a713517 --- /dev/null +++ b/spec/controllers/admin/cohorts_controller_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Admin::CohortsController do + context 'as admin' do + let(:user) { create(:admin) } + + before do + sign_in(user) + end + + it 'renders 200' do + get :index + + expect(response).to have_gitlab_http_status(:success) + end + + describe 'GET #index' do + it_behaves_like 'tracking unique visits', :index do + let(:target_id) { 'i_analytics_cohorts' } + end + end + end + + context 'as normal user' do + let(:user) { create(:user) } + + before do + sign_in(user) + end + + it 'renders a 404' do + get :index + + expect(response).to have_gitlab_http_status(:not_found) + end + end +end diff --git a/spec/controllers/admin/dev_ops_report_controller_spec.rb b/spec/controllers/admin/dev_ops_report_controller_spec.rb new file mode 100644 index 00000000000..0be30fff0c2 --- /dev/null +++ b/spec/controllers/admin/dev_ops_report_controller_spec.rb @@ -0,0 +1,39 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Admin::DevOpsReportController do + describe 'GET #show' do + context 'as admin' do + let(:user) { create(:admin) } + + before do + sign_in(user) + end + + it 'responds with success' do + get :show + + expect(response).to have_gitlab_http_status(:success) + end + + it_behaves_like 'tracking unique visits', :show do + let(:target_id) { 'i_analytics_dev_ops_score' } + end + end + end + + context 'as normal user' do + let(:user) { create(:user) } + + before do + sign_in(user) + end + + it 'responds with 404' do + get :show + + expect(response).to have_gitlab_http_status(:not_found) + end + end +end diff --git a/spec/controllers/admin/instance_statistics_controller_spec.rb b/spec/controllers/admin/instance_statistics_controller_spec.rb new file mode 100644 index 00000000000..c589e46857f --- /dev/null +++ b/spec/controllers/admin/instance_statistics_controller_spec.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Admin::InstanceStatisticsController do + let(:admin) { create(:user, :admin) } + + before do + sign_in(admin) + end + + describe 'GET #show' do + it_behaves_like 'tracking unique visits', :index do + let(:target_id) { 'i_analytics_instance_statistics' } + end + end +end diff --git a/spec/controllers/admin/integrations_controller_spec.rb b/spec/controllers/admin/integrations_controller_spec.rb index 4a5d5ede728..4b1806a43d2 100644 --- a/spec/controllers/admin/integrations_controller_spec.rb +++ b/spec/controllers/admin/integrations_controller_spec.rb @@ -23,12 +23,15 @@ RSpec.describe Admin::IntegrationsController do end describe '#update' do + include JiraServiceHelper + let(:integration) { create(:jira_service, :instance) } before do + stub_jira_service_test allow(PropagateIntegrationWorker).to receive(:perform_async) - put :update, params: { id: integration.class.to_param, overwrite: true, service: { url: url } } + put :update, params: { id: integration.class.to_param, service: { url: url } } end context 'valid params' do @@ -40,7 +43,7 @@ RSpec.describe Admin::IntegrationsController do end it 'calls to PropagateIntegrationWorker' do - expect(PropagateIntegrationWorker).to have_received(:perform_async).with(integration.id, true) + expect(PropagateIntegrationWorker).to have_received(:perform_async).with(integration.id, false) end end diff --git a/spec/controllers/admin/plan_limits_controller_spec.rb b/spec/controllers/admin/plan_limits_controller_spec.rb new file mode 100644 index 00000000000..2666925c2b7 --- /dev/null +++ b/spec/controllers/admin/plan_limits_controller_spec.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Admin::PlanLimitsController do + let_it_be(:plan) { create(:plan) } + let_it_be(:plan_limits) { create(:plan_limits, plan: plan) } + + describe 'POST create' do + let(:params) do + { + plan_limits: { + plan_id: plan.id, + conan_max_file_size: file_size, id: plan_limits.id + } + } + end + + context 'with an authenticated admin user' do + let(:file_size) { 10.megabytes } + + it 'updates the plan limits', :aggregate_failures do + sign_in(create(:admin)) + + post :create, params: params + + expect(response).to redirect_to(general_admin_application_settings_path) + expect(plan_limits.reload.conan_max_file_size).to eq(file_size) + end + end + + context 'without admin access' do + let(:file_size) { 1.megabytes } + + it 'returns `not_found`' do + sign_in(create(:user)) + + post :create, params: params + + expect(response).to have_gitlab_http_status(:not_found) + expect(plan_limits.conan_max_file_size).not_to eq(file_size) + end + end + end +end diff --git a/spec/controllers/admin/sessions_controller_spec.rb b/spec/controllers/admin/sessions_controller_spec.rb index 82366cc6952..35982e57034 100644 --- a/spec/controllers/admin/sessions_controller_spec.rb +++ b/spec/controllers/admin/sessions_controller_spec.rb @@ -220,10 +220,8 @@ RSpec.describe Admin::SessionsController, :do_not_mock_admin_mode do end end - context 'when using two-factor authentication via U2F' do - let(:user) { create(:admin, :two_factor_via_u2f) } - - def authenticate_2fa_u2f(user_params) + shared_examples 'when using two-factor authentication via hardware device' do + def authenticate_2fa(user_params) post(:create, params: { user: user_params }, session: { otp_user_id: user.id }) end @@ -239,14 +237,18 @@ RSpec.describe Admin::SessionsController, :do_not_mock_admin_mode do end it 'can login with valid auth' do + # we can stub both without an differentiation between webauthn / u2f + # as these not interfere with each other und this saves us passing aroud + # parameters allow(U2fRegistration).to receive(:authenticate).and_return(true) + allow_any_instance_of(Webauthn::AuthenticateService).to receive(:execute).and_return(true) expect(controller.current_user_mode.admin_mode?).to be(false) controller.store_location_for(:redirect, admin_root_path) controller.current_user_mode.request_admin_mode! - authenticate_2fa_u2f(login: user.username, device_response: '{}') + authenticate_2fa(login: user.username, device_response: '{}') expect(response).to redirect_to admin_root_path expect(controller.current_user_mode.admin_mode?).to be(true) @@ -254,16 +256,33 @@ RSpec.describe Admin::SessionsController, :do_not_mock_admin_mode do it 'cannot login with invalid auth' do allow(U2fRegistration).to receive(:authenticate).and_return(false) + allow_any_instance_of(Webauthn::AuthenticateService).to receive(:execute).and_return(false) expect(controller.current_user_mode.admin_mode?).to be(false) controller.current_user_mode.request_admin_mode! - authenticate_2fa_u2f(login: user.username, device_response: '{}') + authenticate_2fa(login: user.username, device_response: '{}') expect(response).to render_template('admin/sessions/two_factor') expect(controller.current_user_mode.admin_mode?).to be(false) end end + + context 'when using two-factor authentication via U2F' do + it_behaves_like 'when using two-factor authentication via hardware device' do + let(:user) { create(:admin, :two_factor_via_u2f) } + + before do + stub_feature_flags(webauthn: false) + end + end + end + + context 'when using two-factor authentication via WebAuthn' do + it_behaves_like 'when using two-factor authentication via hardware device' do + let(:user) { create(:admin, :two_factor_via_webauthn) } + end + end end end diff --git a/spec/controllers/admin/users_controller_spec.rb b/spec/controllers/admin/users_controller_spec.rb index 08a1d7c9fa9..e4cdcda756b 100644 --- a/spec/controllers/admin/users_controller_spec.rb +++ b/spec/controllers/admin/users_controller_spec.rb @@ -218,28 +218,44 @@ RSpec.describe Admin::UsersController do end describe 'PATCH disable_two_factor' do - it 'disables 2FA for the user' do - expect(user).to receive(:disable_two_factor!) - allow(subject).to receive(:user).and_return(user) + subject { patch :disable_two_factor, params: { id: user.to_param } } - go - end + context 'for a user that has 2FA enabled' do + let(:user) { create(:user, :two_factor) } - it 'redirects back' do - go + it 'disables 2FA for the user' do + subject - expect(response).to redirect_to(admin_user_path(user)) - end + expect(user.reload.two_factor_enabled?).to eq(false) + end + + it 'redirects back' do + subject + + expect(response).to redirect_to(admin_user_path(user)) + end - it 'displays an alert' do - go + it 'displays a notice on success' do + subject - expect(flash[:notice]) - .to eq _('Two-factor Authentication has been disabled for this user') + expect(flash[:notice]) + .to eq _('Two-factor authentication has been disabled for this user') + end end - def go - patch :disable_two_factor, params: { id: user.to_param } + context 'for a user that does not have 2FA enabled' do + it 'redirects back' do + subject + + expect(response).to redirect_to(admin_user_path(user)) + end + + it 'displays an alert on failure' do + subject + + expect(flash[:alert]) + .to eq _('Two-factor authentication is not enabled for this user') + end end end @@ -270,82 +286,111 @@ RSpec.describe Admin::UsersController do describe 'POST update' do context 'when the password has changed' do - def update_password(user, password, password_confirmation = nil) + def update_password(user, password = User.random_password, password_confirmation = password) params = { id: user.to_param, user: { password: password, - password_confirmation: password_confirmation || password + password_confirmation: password_confirmation } } post :update, params: params end - context 'when the admin changes their own password' do - it 'updates the password' do - expect { update_password(admin, 'AValidPassword1') } - .to change { admin.reload.encrypted_password } - end - - it 'does not set the new password to expire immediately' do - expect { update_password(admin, 'AValidPassword1') } - .not_to change { admin.reload.password_expires_at } + context 'when admin changes their own password' do + context 'when password is valid' do + it 'updates the password' do + expect { update_password(admin) } + .to change { admin.reload.encrypted_password } + end + + it 'does not set the new password to expire immediately' do + expect { update_password(admin) } + .not_to change { admin.reload.password_expired? } + end + + it 'does not enqueue the `admin changed your password` email' do + expect { update_password(admin) } + .not_to have_enqueued_mail(DeviseMailer, :password_change_by_admin) + end + + it 'enqueues the `password changed` email' do + expect { update_password(admin) } + .to have_enqueued_mail(DeviseMailer, :password_change) + end end end - context 'when the new password is valid' do - it 'redirects to the user' do - update_password(user, 'AValidPassword1') - - expect(response).to redirect_to(admin_user_path(user)) - end - - it 'updates the password' do - expect { update_password(user, 'AValidPassword1') } - .to change { user.reload.encrypted_password } - end - - it 'sets the new password to expire immediately' do - expect { update_password(user, 'AValidPassword1') } - .to change { user.reload.password_expires_at }.to be_within(2.seconds).of(Time.current) + context 'when admin changes the password of another user' do + context 'when the new password is valid' do + it 'redirects to the user' do + update_password(user) + + expect(response).to redirect_to(admin_user_path(user)) + end + + it 'updates the password' do + expect { update_password(user) } + .to change { user.reload.encrypted_password } + end + + it 'sets the new password to expire immediately' do + expect { update_password(user) } + .to change { user.reload.password_expired? }.from(false).to(true) + end + + it 'enqueues the `admin changed your password` email' do + expect { update_password(user) } + .to have_enqueued_mail(DeviseMailer, :password_change_by_admin) + end + + it 'does not enqueue the `password changed` email' do + expect { update_password(user) } + .not_to have_enqueued_mail(DeviseMailer, :password_change) + end end end context 'when the new password is invalid' do + let(:password) { 'invalid' } + it 'shows the edit page again' do - update_password(user, 'invalid') + update_password(user, password) expect(response).to render_template(:edit) end it 'returns the error message' do - update_password(user, 'invalid') + update_password(user, password) expect(assigns[:user].errors).to contain_exactly(a_string_matching(/too short/)) end it 'does not update the password' do - expect { update_password(user, 'invalid') } + expect { update_password(user, password) } .not_to change { user.reload.encrypted_password } end end context 'when the new password does not match the password confirmation' do + let(:password) { 'some_password' } + let(:password_confirmation) { 'not_same_as_password' } + it 'shows the edit page again' do - update_password(user, 'AValidPassword1', 'AValidPassword2') + update_password(user, password, password_confirmation) expect(response).to render_template(:edit) end it 'returns the error message' do - update_password(user, 'AValidPassword1', 'AValidPassword2') + update_password(user, password, password_confirmation) expect(assigns[:user].errors).to contain_exactly(a_string_matching(/doesn't match/)) end it 'does not update the password' do - expect { update_password(user, 'AValidPassword1', 'AValidPassword2') } + expect { update_password(user, password, password_confirmation) } .not_to change { user.reload.encrypted_password } end end |