Commit 1cf21b3d authored by Jan Provaznik's avatar Jan Provaznik

Merge branch 'refactor-jira-contr-validations' into 'master'

Refactor validations in JiraController

See merge request gitlab-org/gitlab!31604
parents b0a132e6 8ea97595
...@@ -4,27 +4,30 @@ module Projects ...@@ -4,27 +4,30 @@ module Projects
module Import module Import
class JiraController < Projects::ApplicationController class JiraController < Projects::ApplicationController
before_action :authenticate_user! before_action :authenticate_user!
before_action :check_issues_available!
before_action :authorize_read_project! before_action :authorize_read_project!
before_action :authorize_admin_project!, only: [:import] before_action :validate_jira_import_settings!
def show def show
end end
def import private
jira_project_key = jira_import_params[:jira_project_key]
if jira_project_key.present? def validate_jira_import_settings!
response = ::JiraImport::StartImportService.new(current_user, @project, jira_project_key).execute Gitlab::JiraImport.validate_project_settings!(@project, user: current_user, configuration_check: false)
flash[:notice] = response.message if response.message.present?
else true
flash[:alert] = 'No Jira project key has been provided.' rescue Projects::ImportService::Error => e
end flash[:notice] = e.message
redirect_to project_issues_path(@project)
redirect_to project_import_jira_path(@project) false
end end
private def jira_service
strong_memoize(:jira_service) do
@project.jira_service
end
end
def jira_import_params def jira_import_params
params.permit(:jira_project_key) params.permit(:jira_project_key)
......
...@@ -203,6 +203,10 @@ class JiraService < IssueTrackerService ...@@ -203,6 +203,10 @@ class JiraService < IssueTrackerService
add_comment(data, jira_issue) add_comment(data, jira_issue)
end end
def valid_connection?
test(nil)[:success]
end
def test(_) def test(_)
result = test_settings result = test_settings
success = result.present? success = result.present?
......
.js-jira-import-root{ data: { project_path: @project.full_path, .js-jira-import-root{ data: { project_path: @project.full_path,
issues_path: project_issues_path(@project), issues_path: project_issues_path(@project),
jira_integration_path: edit_project_service_path(@project, :jira), jira_integration_path: edit_project_service_path(@project, :jira),
is_jira_configured: @project.jira_service.present?.to_s, is_jira_configured: @project.jira_service&.valid_connection?.to_s,
in_progress_illustration: image_path('illustrations/export-import.svg'), in_progress_illustration: image_path('illustrations/export-import.svg'),
setup_illustration: image_path('illustrations/manual_action.svg') } } setup_illustration: image_path('illustrations/manual_action.svg') } }
...@@ -324,9 +324,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do ...@@ -324,9 +324,7 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
draw :wiki draw :wiki
namespace :import do namespace :import do
resource :jira, only: [:show], controller: :jira do resource :jira, only: [:show], controller: :jira
post :import
end
end end
end end
# End of the /-/ scope. # End of the /-/ scope.
......
...@@ -10,16 +10,18 @@ module Gitlab ...@@ -10,16 +10,18 @@ module Gitlab
ITEMS_MAPPER_CACHE_KEY = 'jira-import/items-mapper/%{project_id}/%{collection_type}/%{jira_isssue_id}' ITEMS_MAPPER_CACHE_KEY = 'jira-import/items-mapper/%{project_id}/%{collection_type}/%{jira_isssue_id}'
ALREADY_IMPORTED_ITEMS_CACHE_KEY = 'jira-importer/already-imported/%{project}/%{collection_type}' ALREADY_IMPORTED_ITEMS_CACHE_KEY = 'jira-importer/already-imported/%{project}/%{collection_type}'
def self.validate_project_settings!(project, user: nil) def self.validate_project_settings!(project, user: nil, configuration_check: true)
if user if user
raise Projects::ImportService::Error, _('Cannot import because issues are not available in this project.') unless project.feature_available?(:issues, user) raise Projects::ImportService::Error, _('Cannot import because issues are not available in this project.') unless project.feature_available?(:issues, user)
raise Projects::ImportService::Error, _('You do not have permissions to run the import.') unless user.can?(:admin_project, project) raise Projects::ImportService::Error, _('You do not have permissions to run the import.') unless user.can?(:admin_project, project)
end end
return unless configuration_check
jira_service = project.jira_service jira_service = project.jira_service
raise Projects::ImportService::Error, _('Jira integration not configured.') unless jira_service&.active? raise Projects::ImportService::Error, _('Jira integration not configured.') unless jira_service&.active?
raise Projects::ImportService::Error, _('Unable to connect to the Jira instance. Please check your Jira integration configuration.') unless jira_service.test(nil)[:success] raise Projects::ImportService::Error, _('Unable to connect to the Jira instance. Please check your Jira integration configuration.') unless jira_service&.valid_connection?
end end
def self.jira_issue_cache_key(project_id, jira_issue_id) def self.jira_issue_cache_key(project_id, jira_issue_id)
......
...@@ -9,142 +9,94 @@ RSpec.describe Projects::Import::JiraController do ...@@ -9,142 +9,94 @@ RSpec.describe Projects::Import::JiraController do
let_it_be(:project) { create(:project) } let_it_be(:project) { create(:project) }
let_it_be(:jira_project_key) { 'Test' } let_it_be(:jira_project_key) { 'Test' }
context 'with anonymous user' do def ensure_correct_config
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: jira_project_key }
expect(response).to redirect_to(new_user_session_path)
end
end
end
context 'with logged in user' do
before do
sign_in(user) sign_in(user)
project.add_maintainer(user) project.add_maintainer(user)
stub_feature_flags(jira_issue_import: true)
stub_jira_service_test stub_jira_service_test
end end
context 'when Jira service is enabled for the project' do shared_examples 'redirect with error' do |error|
let_it_be(:jira_service) { create(:jira_service, project: project) } it 'redirects to project issues path' do
subject
context 'when user is developer' do
let_it_be(:dev) { create(:user) }
before do expect(response).to redirect_to(project_issues_path(project))
sign_in(dev)
project.add_developer(dev)
end end
context 'get show' do it 'renders a correct error' do
before do subject
get :show, params: { namespace_id: project.namespace.to_param, project_id: project }
end
it 'does not query Jira service' do expect(flash[:notice]).to eq(error)
expect(project).not_to receive(:jira_service)
end
it 'renders show template' do
expect(response).to render_template(:show)
end end
end end
context 'post import' do shared_examples 'template with no message' do
it 'returns 404' do it 'does not set any message' do
post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: jira_project_key } subject
expect(response).to have_gitlab_http_status(:not_found) expect(flash).to be_empty
end end
end
end
context 'when issues disabled' do
let_it_be(:disabled_issues_project) { create(:project, :public, :issues_disabled) }
context 'get show' do it 'renders show template' do
it 'returns 404' do subject
get :show, params: { namespace_id: project.namespace.to_param, project_id: disabled_issues_project }
expect(response).to have_gitlab_http_status(:not_found) expect(response).to render_template(template)
end end
end end
context 'post import' do shared_examples 'users without permissions' do
it 'returns 404' do context 'with anonymous user' do
post :import, params: { namespace_id: disabled_issues_project.namespace, project_id: disabled_issues_project, jira_project_key: jira_project_key } it 'redirects to new user page' do
subject
expect(response).to have_gitlab_http_status(:not_found) expect(response).to redirect_to(new_user_session_path)
end
end end
end end
context 'when running Jira import first time' do context 'when loged user is a developer' do
context 'post import' do before do
context 'when Jira project key is empty' do create(:jira_service, project: project)
it 'redirects back to show with an error' do stub_jira_service_test
post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: '' }
expect(response).to redirect_to(project_import_jira_path(project)) sign_in(user)
expect(flash[:alert]).to eq('No Jira project key has been provided.') project.add_developer(user)
end
end end
context 'when everything is ok' do it_behaves_like 'redirect with error', 'You do not have permissions to run the import.'
it 'creates import state' do
expect(project.latest_jira_import).to be_nil
post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: jira_project_key }
project.reload
jira_import = project.latest_jira_import
expect(project.import_type).to eq 'jira'
expect(jira_import.status).to eq 'scheduled'
expect(jira_import.jira_project_key).to eq jira_project_key
expect(response).to redirect_to(project_import_jira_path(project))
end
end
end end
end end
context 'when import state is scheduled' do describe 'GET #show' do
let_it_be(:jira_import_state) { create(:jira_import_state, :scheduled, project: project) } let(:template) { 'show' }
context 'post import' do subject { get :show, params: { namespace_id: project.namespace, project_id: project } }
it 'uses the existing import data' do
post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'New Project' }
expect(flash[:notice]).to eq('Jira import is already running.') it_behaves_like 'users without permissions'
expect(response).to redirect_to(project_import_jira_path(project))
end context 'jira service configuration' do
before do
sign_in(user)
project.add_maintainer(user)
stub_feature_flags(jira_issue_import: true)
end end
context 'when Jira service is not enabled for the project' do
it 'does not query Jira service' do
expect(project).not_to receive(:jira_service)
end end
context 'when Jira import ran before' do it_behaves_like 'template with no message'
let_it_be(:jira_import_state) { create(:jira_import_state, :finished, project: project, jira_project_key: jira_project_key) } end
context 'post import' do context 'when Jira service is not configured correctly for the project' do
it 'uses the existing import data' do let_it_be(:jira_service) { create(:jira_service, project: project) }
post :import, params: { namespace_id: project.namespace, project_id: project, jira_project_key: 'New Project' }
project.reload before do
expect(project.latest_jira_import.status).to eq 'scheduled' WebMock.stub_request(:get, 'https://jira.example.com/rest/api/2/serverInfo')
expect(project.jira_imports.size).to eq 2 .to_raise(JIRA::HTTPError.new(double(message: 'Some failure.')))
expect(project.jira_imports.first.jira_project_key).to eq jira_project_key
expect(project.jira_imports.last.jira_project_key).to eq 'New Project'
expect(response).to redirect_to(project_import_jira_path(project))
end
end end
it_behaves_like 'template with no message'
end end
end end
end end
......
...@@ -9,6 +9,9 @@ describe Gitlab::JiraImport do ...@@ -9,6 +9,9 @@ describe Gitlab::JiraImport do
include JiraServiceHelper include JiraServiceHelper
let_it_be(:project, reload: true) { create(:project) } let_it_be(:project, reload: true) { create(:project) }
let(:additional_params) { {} }
subject { described_class.validate_project_settings!(project, additional_params) }
shared_examples 'raise Jira import error' do |message| shared_examples 'raise Jira import error' do |message|
it 'returns error' do it 'returns error' do
...@@ -17,6 +20,16 @@ describe Gitlab::JiraImport do ...@@ -17,6 +20,16 @@ describe Gitlab::JiraImport do
end end
shared_examples 'jira configuration base checks' do shared_examples 'jira configuration base checks' do
context 'with configuration_check set to false' do
before do
additional_params[:configuration_check] = false
end
it 'does not raise Jira integration error' do
expect { subject }.not_to raise_error
end
end
context 'when Jira service was not setup' do context 'when Jira service was not setup' do
it_behaves_like 'raise Jira import error', 'Jira integration not configured.' it_behaves_like 'raise Jira import error', 'Jira integration not configured.'
end end
...@@ -40,8 +53,6 @@ describe Gitlab::JiraImport do ...@@ -40,8 +53,6 @@ describe Gitlab::JiraImport do
end end
context 'without user param' do context 'without user param' do
subject { described_class.validate_project_settings!(project) }
it_behaves_like 'jira configuration base checks' it_behaves_like 'jira configuration base checks'
context 'when jira connection is valid' do context 'when jira connection is valid' do
...@@ -56,7 +67,7 @@ describe Gitlab::JiraImport do ...@@ -56,7 +67,7 @@ describe Gitlab::JiraImport do
context 'with user param provided' do context 'with user param provided' do
let_it_be(:user) { create(:user) } let_it_be(:user) { create(:user) }
subject { described_class.validate_project_settings!(project, user: user) } let(:additional_params) { { user: user } }
context 'when user has permission to run import' do context 'when user has permission to run import' do
before do before do
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment