diff options
Diffstat (limited to 'spec/controllers')
-rw-r--r-- | spec/controllers/admin/sessions_controller_spec.rb | 116 | ||||
-rw-r--r-- | spec/controllers/projects/import/jira_controller_spec.rb | 173 |
2 files changed, 284 insertions, 5 deletions
diff --git a/spec/controllers/admin/sessions_controller_spec.rb b/spec/controllers/admin/sessions_controller_spec.rb index 4bab6b51102..fabd79133ec 100644 --- a/spec/controllers/admin/sessions_controller_spec.rb +++ b/spec/controllers/admin/sessions_controller_spec.rb @@ -68,7 +68,7 @@ describe Admin::SessionsController, :do_not_mock_admin_mode do # triggering the auth form will request admin mode get :new - post :create, params: { password: user.password } + post :create, params: { user: { password: user.password } } expect(response).to redirect_to admin_root_path expect(controller.current_user_mode.admin_mode?).to be(true) @@ -82,7 +82,7 @@ describe Admin::SessionsController, :do_not_mock_admin_mode do # triggering the auth form will request admin mode get :new - post :create, params: { password: '' } + post :create, params: { user: { password: '' } } expect(response).to render_template :new expect(controller.current_user_mode.admin_mode?).to be(false) @@ -95,7 +95,7 @@ describe Admin::SessionsController, :do_not_mock_admin_mode do # do not trigger the auth form - post :create, params: { password: user.password } + post :create, params: { user: { password: user.password } } expect(response).to redirect_to(new_admin_session_path) expect(controller.current_user_mode.admin_mode?).to be(false) @@ -110,12 +110,118 @@ describe Admin::SessionsController, :do_not_mock_admin_mode do get :new Timecop.freeze(Gitlab::Auth::CurrentUserMode::ADMIN_MODE_REQUESTED_GRACE_PERIOD.from_now) do - post :create, params: { password: user.password } + post :create, params: { user: { password: user.password } } expect(response).to redirect_to(new_admin_session_path) expect(controller.current_user_mode.admin_mode?).to be(false) end end + + context 'when using two-factor authentication via OTP' do + let(:user) { create(:admin, :two_factor) } + + def authenticate_2fa(user_params) + post(:create, params: { user: user_params }, session: { otp_user_id: user.id }) + end + + it 'requests two factor after a valid password is provided' do + expect(controller.current_user_mode.admin_mode?).to be(false) + + # triggering the auth form will request admin mode + get :new + + post :create, params: { user: { password: user.password } } + + expect(response).to render_template('admin/sessions/two_factor') + expect(controller.current_user_mode.admin_mode?).to be(false) + end + + it 'can login with valid otp' do + 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(otp_attempt: user.current_otp) + + expect(response).to redirect_to admin_root_path + expect(controller.current_user_mode.admin_mode?).to be(true) + end + + it 'cannot login with invalid otp' do + expect(controller.current_user_mode.admin_mode?).to be(false) + + controller.current_user_mode.request_admin_mode! + + authenticate_2fa(otp_attempt: 'invalid') + + expect(response).to render_template('admin/sessions/two_factor') + expect(controller.current_user_mode.admin_mode?).to be(false) + end + + context 'with password authentication disabled' do + before do + stub_application_setting(password_authentication_enabled_for_web: false) + end + + it 'allows 2FA stage of non-password login' do + 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(otp_attempt: user.current_otp) + + expect(response).to redirect_to admin_root_path + expect(controller.current_user_mode.admin_mode?).to be(true) + end + 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) + post(:create, params: { user: user_params }, session: { otp_user_id: user.id }) + end + + it 'requests two factor after a valid password is provided' do + expect(controller.current_user_mode.admin_mode?).to be(false) + + # triggering the auth form will request admin mode + get :new + post :create, params: { user: { password: user.password } } + + expect(response).to render_template('admin/sessions/two_factor') + expect(controller.current_user_mode.admin_mode?).to be(false) + end + + it 'can login with valid auth' do + allow(U2fRegistration).to receive(:authenticate).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: '{}') + + expect(response).to redirect_to admin_root_path + expect(controller.current_user_mode.admin_mode?).to be(true) + end + + it 'cannot login with invalid auth' do + allow(U2fRegistration).to receive(:authenticate).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: '{}') + + expect(response).to render_template('admin/sessions/two_factor') + expect(controller.current_user_mode.admin_mode?).to be(false) + end + end end end @@ -136,7 +242,7 @@ describe Admin::SessionsController, :do_not_mock_admin_mode do expect(controller.current_user_mode.admin_mode?).to be(false) get :new - post :create, params: { password: user.password } + post :create, params: { user: { password: user.password } } expect(controller.current_user_mode.admin_mode?).to be(true) post :destroy diff --git a/spec/controllers/projects/import/jira_controller_spec.rb b/spec/controllers/projects/import/jira_controller_spec.rb new file mode 100644 index 00000000000..9d68104b755 --- /dev/null +++ b/spec/controllers/projects/import/jira_controller_spec.rb @@ -0,0 +1,173 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe Projects::Import::JiraController do + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project) } + + context 'with anonymous user' do + before do + stub_feature_flags(jira_issue_import: true) + end + + context 'get show' do + it 'redirects to issues page' do + get :show, params: { namespace_id: project.namespace, project_id: project } + + expect(response).to redirect_to(new_user_session_path) + end + end + + context 'post import' do + it 'redirects to issues page' do + post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'Test' } + + expect(response).to redirect_to(new_user_session_path) + end + end + end + + context 'with logged in user' do + before do + sign_in(user) + project.add_maintainer(user) + end + + context 'when feature flag not enabled' do + before do + stub_feature_flags(jira_issue_import: false) + end + + context 'get show' do + it 'redirects to issues page' do + get :show, params: { namespace_id: project.namespace, project_id: project } + + expect(response).to redirect_to(project_issues_path(project)) + end + end + + context 'post import' do + it 'redirects to issues page' do + post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'Test' } + + expect(response).to redirect_to(project_issues_path(project)) + end + end + end + + context 'when feature flag enabled' do + before do + stub_feature_flags(jira_issue_import: true) + end + + context 'when jira service is enabled for the project' do + let_it_be(:jira_service) { create(:jira_service, project: project) } + + context 'when running jira import first time' do + context 'get show' do + it 'renders show template' do + allow(JIRA::Resource::Project).to receive(:all).and_return([]) + expect(project.import_state).to be_nil + + get :show, params: { namespace_id: project.namespace.to_param, project_id: project } + + expect(response).to render_template :show + end + end + + context 'post import' do + it 'creates import state' do + expect(project.import_state).to be_nil + + post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'Test' } + + project.reload + + jira_project = project.import_data.data.dig('jira', 'projects').first + expect(project.import_type).to eq 'jira' + expect(project.import_state.status).to eq 'scheduled' + expect(jira_project['key']).to eq 'Test' + expect(response).to redirect_to(project_import_jira_path(project)) + end + end + end + + context 'when import state is scheduled' do + let_it_be(:import_state) { create(:import_state, project: project, status: :scheduled) } + + context 'get show' do + it 'renders import status' do + get :show, params: { namespace_id: project.namespace.to_param, project_id: project } + + expect(project.import_state.status).to eq 'scheduled' + expect(flash.now[:notice]).to eq 'Import scheduled' + end + end + + context 'post import' do + before do + project.reload + project.create_import_data( + data: { + 'jira': { + 'projects': [{ 'key': 'Test', scheduled_at: 5.days.ago, scheduled_by: { user_id: user.id, name: user.name } }] + } + } + ) + end + + it 'uses the existing import data' do + expect(controller).not_to receive(:schedule_import) + + post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'New Project' } + + expect(response).to redirect_to(project_import_jira_path(project)) + end + end + end + + context 'when jira import ran before' do + let_it_be(:import_state) { create(:import_state, project: project, status: :finished) } + + context 'get show' do + it 'renders import status' do + allow(JIRA::Resource::Project).to receive(:all).and_return([]) + get :show, params: { namespace_id: project.namespace.to_param, project_id: project } + + expect(project.import_state.status).to eq 'finished' + expect(flash.now[:notice]).to eq 'Import finished' + end + end + + context 'post import' do + before do + project.reload + project.create_import_data( + data: { + 'jira': { + 'projects': [{ 'key': 'Test', scheduled_at: 5.days.ago, scheduled_by: { user_id: user.id, name: user.name } }] + } + } + ) + end + + it 'uses the existing import data' do + expect(controller).to receive(:schedule_import).and_call_original + + post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'New Project' } + + project.reload + expect(project.import_state.status).to eq 'scheduled' + jira_imported_projects = project.import_data.data.dig('jira', 'projects') + expect(jira_imported_projects.size).to eq 2 + expect(jira_imported_projects.first['key']).to eq 'Test' + expect(jira_imported_projects.last['key']).to eq 'New Project' + expect(response).to redirect_to(project_import_jira_path(project)) + end + end + end + end + end + end +end |