From ef807a2ecaa6841baa3b38d48f09df59823582f0 Mon Sep 17 00:00:00 2001 From: Reuben Pereira Date: Wed, 6 Feb 2019 15:07:26 +0000 Subject: [PATCH] Add service to get sentry projects list --- .../error_tracking/list_projects_service.rb | 44 ++++++ .../list_projects_service_spec.rb | 149 ++++++++++++++++++ 2 files changed, 193 insertions(+) create mode 100644 app/services/error_tracking/list_projects_service.rb create mode 100644 spec/services/error_tracking/list_projects_service_spec.rb diff --git a/app/services/error_tracking/list_projects_service.rb b/app/services/error_tracking/list_projects_service.rb new file mode 100644 index 00000000000..c6e8be0f2be --- /dev/null +++ b/app/services/error_tracking/list_projects_service.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +module ErrorTracking + class ListProjectsService < ::BaseService + def execute + return error('access denied') unless can_read? + + setting = project_error_tracking_setting + + unless setting.valid? + return error(setting.errors.full_messages.join(', '), :bad_request) + end + + begin + result = setting.list_sentry_projects + rescue Sentry::Client::Error => e + return error(e.message, :bad_request) + rescue Sentry::Client::SentryError => e + return error(e.message, :unprocessable_entity) + end + + success(projects: result[:projects]) + end + + private + + def project_error_tracking_setting + (project.error_tracking_setting || project.build_error_tracking_setting).tap do |setting| + setting.api_url = ErrorTracking::ProjectErrorTrackingSetting.build_api_url_from( + api_host: params[:api_host], + organization_slug: nil, + project_slug: nil + ) + + setting.token = params[:token] + setting.enabled = true + end + end + + def can_read? + can?(current_user, :read_sentry_issue, project) + end + end +end diff --git a/spec/services/error_tracking/list_projects_service_spec.rb b/spec/services/error_tracking/list_projects_service_spec.rb new file mode 100644 index 00000000000..ee9c59e3f65 --- /dev/null +++ b/spec/services/error_tracking/list_projects_service_spec.rb @@ -0,0 +1,149 @@ +# frozen_string_literal: true + +require 'spec_helper' + +describe ErrorTracking::ListProjectsService do + set(:user) { create(:user) } + set(:project) { create(:project) } + + let(:sentry_url) { 'https://sentrytest.gitlab.com/api/0/projects/sentry-org/sentry-project' } + let(:token) { 'test-token' } + let(:new_api_host) { 'https://gitlab.com/' } + let(:new_token) { 'new-token' } + let(:params) { ActionController::Parameters.new(api_host: new_api_host, token: new_token) } + + let(:error_tracking_setting) do + create(:project_error_tracking_setting, api_url: sentry_url, token: token, project: project) + end + + subject { described_class.new(project, user, params) } + + before do + project.add_reporter(user) + end + + describe '#execute' do + let(:result) { subject.execute } + + context 'with authorized user' do + before do + expect(project).to receive(:error_tracking_setting).at_least(:once) + .and_return(error_tracking_setting) + end + + context 'set model attributes to new values' do + let(:new_api_url) { new_api_host + 'api/0/projects/' } + + before do + expect(error_tracking_setting).to receive(:list_sentry_projects) + .and_return({ projects: [] }) + end + + it 'uses new api_url and token' do + subject.execute + + expect(error_tracking_setting.api_url).to eq(new_api_url) + expect(error_tracking_setting.token).to eq(new_token) + error_tracking_setting.reload + expect(error_tracking_setting.api_url).to eq(sentry_url) + expect(error_tracking_setting.token).to eq(token) + end + end + + context 'sentry client raises exception' do + before do + expect(error_tracking_setting).to receive(:list_sentry_projects) + .and_raise(Sentry::Client::Error, 'Sentry response error: 500') + end + + it 'returns error response' do + expect(result[:message]).to eq('Sentry response error: 500') + expect(result[:http_status]).to eq(:bad_request) + end + end + + context 'with invalid url' do + let(:params) do + ActionController::Parameters.new( + api_host: 'https://localhost', + token: new_token + ) + end + + before do + error_tracking_setting.enabled = false + end + + it 'returns error' do + expect(result[:message]).to start_with('Api url is blocked') + expect(error_tracking_setting).not_to be_valid + end + end + + context 'when list_sentry_projects returns projects' do + let(:projects) { [:list, :of, :projects] } + + before do + expect(error_tracking_setting) + .to receive(:list_sentry_projects).and_return(projects: projects) + end + + it 'returns the projects' do + expect(result).to eq(status: :success, projects: projects) + end + end + end + + context 'with unauthorized user' do + before do + project.add_guest(user) + end + + it 'returns error' do + expect(result).to include(status: :error, message: 'access denied') + end + end + + context 'with error tracking disabled' do + before do + expect(project).to receive(:error_tracking_setting).at_least(:once) + .and_return(error_tracking_setting) + expect(error_tracking_setting) + .to receive(:list_sentry_projects).and_return(projects: []) + + error_tracking_setting.enabled = false + end + + it 'ignores enabled flag' do + expect(result).to include(status: :success, projects: []) + end + end + + context 'error_tracking_setting is nil' do + let(:error_tracking_setting) { build(:project_error_tracking_setting) } + let(:new_api_url) { new_api_host + 'api/0/projects/' } + + before do + expect(project).to receive(:build_error_tracking_setting).once + .and_return(error_tracking_setting) + + expect(error_tracking_setting).to receive(:list_sentry_projects) + .and_return(projects: [:project1, :project2]) + end + + it 'builds a new error_tracking_setting' do + expect(project.error_tracking_setting).to be_nil + + expect(result[:projects]).to eq([:project1, :project2]) + + expect(error_tracking_setting.api_url).to eq(new_api_url) + expect(error_tracking_setting.token).to eq(new_token) + expect(error_tracking_setting.enabled).to be true + expect(error_tracking_setting.persisted?).to be false + expect(error_tracking_setting.project_id).not_to be_nil + + expect(project.error_tracking_setting).to be_nil + end + end + end +end -- GitLab