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 @@
module Metrics
module Dashboard
class UpdateDashboardService < ::BaseService
include Stepable
ALLOWED_FILE_TYPE = '.yml'
USER_DASHBOARDS_DIR = ::Metrics::Dashboard::ProjectDashboardService::DASHBOARD_ROOT
# rubocop:disable Cop/BanCatchThrow
def execute
catch(:error) do
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?
result = ::Files::UpdateService.new(project, current_user, dashboard_attrs).execute
throw(:error, result.merge(http_status: :bad_request)) unless result[:status] == :success
steps :check_push_authorized,
:check_branch_name,
:check_file_type,
:update_file
success(result.merge(http_status: :created, dashboard: dashboard_details))
end
def execute
execute_steps
end
# rubocop:enable Cop/BanCatchThrow
private
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
}
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?
success(result)
end
def dashboard_details
{
path: update_dashboard_path,
display_name: ::Metrics::Dashboard::ProjectDashboardService.name_for_path(update_dashboard_path),
default: false,
system_dashboard: false
}
def check_branch_name(result)
return error(_('There was an error updating the dashboard, branch name is invalid.'), :bad_request) unless valid_branch_name?
return error(_('There was an error updating the dashboard, branch named: %{branch} already exists.') % { branch: params[:branch] }, :bad_request) unless new_or_default_branch?
success(result)
end
def push_authorized?
Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(branch)
def check_file_type(result)
return error(_('The file name should have a .yml extension'), :bad_request) unless target_file_type_valid?
success(result)
end
# rubocop:disable Cop/BanCatchThrow
def branch
@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?
def update_file(result)
file_update_response = ::Files::UpdateService.new(project, current_user, dashboard_attrs).execute
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
# rubocop:enable Cop/BanCatchThrow
def new_or_default_branch?
!repository.branch_exists?(params[:branch]) || project.default_branch == params[:branch]
def push_authorized?
Gitlab::UserAccess.new(current_user, project: project).can_push_to_branch?(branch)
end
def valid_branch_name?
Gitlab::GitRefValidator.validate(params[:branch])
Gitlab::GitRefValidator.validate(branch)
end
def update_dashboard_path
File.join(USER_DASHBOARDS_DIR, file_name)
def new_or_default_branch?
!repository.branch_exists?(branch) || project.default_branch == branch
end
def target_file_type_valid?
File.extname(params[:file_name]) == ALLOWED_FILE_TYPE
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
@file_name ||= begin
throw(:error, error(_('The file name should have a .yml extension'), :bad_request)) unless target_file_type_valid?
@file_name ||= File.basename(CGI.unescape(params[:file_name]))
end
File.basename(CGI.unescape(params[:file_name]))
end
def branch
@branch ||= params[:branch]
end
# rubocop:enable Cop/BanCatchThrow
def update_dashboard_content
::PerformanceMonitoring::PrometheusDashboard.from_json(params[:file_content]).to_yaml
......@@ -90,6 +95,15 @@ module Metrics
def repository
@repository ||= project.repository
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
......@@ -27,7 +27,14 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto
end
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
context 'with rights to push to the repository' do
......@@ -39,13 +46,27 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto
context 'with a yml extension' do
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
context 'without a yml extension' do
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
......@@ -60,7 +81,14 @@ describe Metrics::Dashboard::UpdateDashboardService, :use_clean_rails_memory_sto
project.repository.add_branch(user, branch, 'master')
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
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