Commit 5579dc08 authored by Douglas Barbosa Alexandre's avatar Douglas Barbosa Alexandre

Merge branch '208174-refactor-update-dashboard-service' into 'master'

Refactor UpdateDashboardService to remove catch/throw

See merge request gitlab-org/gitlab!27185
parents f09fc5cc e5385e8f
...@@ -4,84 +4,89 @@ ...@@ -4,84 +4,89 @@
module Metrics module Metrics
module Dashboard module Dashboard
class UpdateDashboardService < ::BaseService class UpdateDashboardService < ::BaseService
include Stepable
ALLOWED_FILE_TYPE = '.yml' ALLOWED_FILE_TYPE = '.yml'
USER_DASHBOARDS_DIR = ::Metrics::Dashboard::ProjectDashboardService::DASHBOARD_ROOT USER_DASHBOARDS_DIR = ::Metrics::Dashboard::ProjectDashboardService::DASHBOARD_ROOT
# rubocop:disable Cop/BanCatchThrow steps :check_push_authorized,
def execute :check_branch_name,
catch(:error) do :check_file_type,
throw(:error, error(_(%q(You are not allowed to push into this branch. Create another branch or open a merge request.)), :forbidden)) unless push_authorized? :update_file
result = ::Files::UpdateService.new(project, current_user, dashboard_attrs).execute
throw(:error, result.merge(http_status: :bad_request)) unless result[:status] == :success
success(result.merge(http_status: :created, dashboard: dashboard_details)) def execute
end execute_steps
end end
# rubocop:enable Cop/BanCatchThrow
private private
def dashboard_attrs def check_push_authorized(result)
{ return error(_('You are not allowed to push into this branch. Create another branch or open a merge request.'), :forbidden) unless push_authorized?
commit_message: params[:commit_message],
file_path: update_dashboard_path, success(result)
file_content: update_dashboard_content,
encoding: 'text',
branch_name: branch,
start_branch: repository.branch_exists?(branch) ? branch : project.default_branch
}
end end
def dashboard_details def check_branch_name(result)
{ return error(_('There was an error updating the dashboard, branch name is invalid.'), :bad_request) unless valid_branch_name?
path: update_dashboard_path, return error(_('There was an error updating the dashboard, branch named: %{branch} already exists.') % { branch: params[:branch] }, :bad_request) unless new_or_default_branch?
display_name: ::Metrics::Dashboard::ProjectDashboardService.name_for_path(update_dashboard_path),
default: false, success(result)
system_dashboard: false
}
end end
def push_authorized? def check_file_type(result)
Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(branch) return error(_('The file name should have a .yml extension'), :bad_request) unless target_file_type_valid?
success(result)
end end
# rubocop:disable Cop/BanCatchThrow def update_file(result)
def branch file_update_response = ::Files::UpdateService.new(project, current_user, dashboard_attrs).execute
@branch ||= begin
throw(:error, error(_('There was an error updating the dashboard, branch name is invalid.'), :bad_request)) unless valid_branch_name?
throw(:error, error(_('There was an error updating the dashboard, branch named: %{branch} already exists.') % { branch: params[:branch] }, :bad_request)) unless new_or_default_branch?
params[:branch] if file_update_response[:status] == :success
success(result.merge(file_update_response, http_status: :created, dashboard: dashboard_details))
else
error(file_update_response[:message], :bad_request)
end end
end end
# rubocop:enable Cop/BanCatchThrow
def new_or_default_branch? def push_authorized?
!repository.branch_exists?(params[:branch]) || project.default_branch == params[:branch] Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(branch)
end end
def valid_branch_name? def valid_branch_name?
Gitlab::GitRefValidator.validate(params[:branch]) Gitlab::GitRefValidator.validate(branch)
end end
def update_dashboard_path def new_or_default_branch?
File.join(USER_DASHBOARDS_DIR, file_name) !repository.branch_exists?(branch) || project.default_branch == branch
end end
def target_file_type_valid? def target_file_type_valid?
File.extname(params[:file_name]) == ALLOWED_FILE_TYPE File.extname(params[:file_name]) == ALLOWED_FILE_TYPE
end end
# rubocop:disable Cop/BanCatchThrow def dashboard_attrs
{
commit_message: params[:commit_message],
file_path: update_dashboard_path,
file_content: update_dashboard_content,
encoding: 'text',
branch_name: branch,
start_branch: repository.branch_exists?(branch) ? branch : project.default_branch
}
end
def update_dashboard_path
File.join(USER_DASHBOARDS_DIR, file_name)
end
def file_name def file_name
@file_name ||= begin @file_name ||= File.basename(CGI.unescape(params[:file_name]))
throw(:error, error(_('The file name should have a .yml extension'), :bad_request)) unless target_file_type_valid? end
File.basename(CGI.unescape(params[:file_name])) def branch
end @branch ||= params[:branch]
end end
# rubocop:enable Cop/BanCatchThrow
def update_dashboard_content def update_dashboard_content
::PerformanceMonitoring::PrometheusDashboard.from_json(params[:file_content]).to_yaml ::PerformanceMonitoring::PrometheusDashboard.from_json(params[:file_content]).to_yaml
...@@ -90,6 +95,15 @@ module Metrics ...@@ -90,6 +95,15 @@ module Metrics
def repository def repository
@repository ||= project.repository @repository ||= project.repository
end end
def dashboard_details
{
path: update_dashboard_path,
display_name: ::Metrics::Dashboard::ProjectDashboardService.name_for_path(update_dashboard_path),
default: false,
system_dashboard: false
}
end
end end
end end
end end
...@@ -27,7 +27,14 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto ...@@ -27,7 +27,14 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto
end end
context 'user does not have push right to repository' do context 'user does not have push right to repository' do
it_behaves_like 'misconfigured dashboard service response', :forbidden, "You are not allowed to push into this branch. Create another branch or open a merge request." it 'returns an appropriate message and status code', :aggregate_failures do
result = service_call
expect(result.keys).to contain_exactly(:message, :http_status, :status, :last_step)
expect(result[:status]).to eq(:error)
expect(result[:http_status]).to eq(:forbidden)
expect(result[:message]).to eq("You are not allowed to push into this branch. Create another branch or open a merge request.")
end
end end
context 'with rights to push to the repository' do context 'with rights to push to the repository' do
...@@ -39,13 +46,27 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto ...@@ -39,13 +46,27 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto
context 'with a yml extension' do context 'with a yml extension' do
let(:file_name) { 'config/prometheus/../database.yml' } let(:file_name) { 'config/prometheus/../database.yml' }
it_behaves_like 'misconfigured dashboard service response', :bad_request, "A file with this name doesn't exist" it 'returns an appropriate message and status code', :aggregate_failures do
result = service_call
expect(result.keys).to contain_exactly(:message, :http_status, :status, :last_step)
expect(result[:status]).to eq(:error)
expect(result[:http_status]).to eq(:bad_request)
expect(result[:message]).to eq("A file with this name doesn't exist")
end
end end
context 'without a yml extension' do context 'without a yml extension' do
let(:file_name) { '../../..../etc/passwd' } let(:file_name) { '../../..../etc/passwd' }
it_behaves_like 'misconfigured dashboard service response', :bad_request, "The file name should have a .yml extension" it 'returns an appropriate message and status code', :aggregate_failures do
result = service_call
expect(result.keys).to contain_exactly(:message, :http_status, :status, :last_step)
expect(result[:status]).to eq(:error)
expect(result[:http_status]).to eq(:bad_request)
expect(result[:message]).to eq("The file name should have a .yml extension")
end
end end
end end
...@@ -60,7 +81,14 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto ...@@ -60,7 +81,14 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto
project.repository.add_branch(user, branch, 'master') project.repository.add_branch(user, branch, 'master')
end end
it_behaves_like 'misconfigured dashboard service response', :bad_request, "There was an error updating the dashboard, branch named: existing_branch already exists." it 'returns an appropriate message and status code', :aggregate_failures do
result = service_call
expect(result.keys).to contain_exactly(:message, :http_status, :status, :last_step)
expect(result[:status]).to eq(:error)
expect(result[:http_status]).to eq(:bad_request)
expect(result[:message]).to eq("There was an error updating the dashboard, branch named: existing_branch already exists.")
end
end end
context 'Files::UpdateService success' do context 'Files::UpdateService success' 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