From 8f85a11d9fcc1f4ccde7c46652f0be00edf46a78 Mon Sep 17 00:00:00 2001 From: Douwe Maan Date: Sun, 29 Jan 2017 15:31:53 -0600 Subject: [PATCH] Validate route map --- app/models/project.rb | 17 +++---- app/views/projects/blob/_actions.html.haml | 2 +- lib/gitlab/route_map.rb | 52 ++++++++++++++++++++++ 3 files changed, 58 insertions(+), 13 deletions(-) create mode 100644 lib/gitlab/route_map.rb diff --git a/app/models/project.rb b/app/models/project.rb index ad22ab7577e..42a79557136 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -1312,7 +1312,7 @@ class Project < ActiveRecord::Base deployments_query = with_tags ? 'ref = ? OR tag IS TRUE' : 'ref = ?' deployments.where(deployments_query, ref.to_s) elsif commit - deps = deployments.where(sha: commit.sha) + deployments.where(sha: commit.sha) else Deployment.none end @@ -1348,13 +1348,9 @@ class Project < ActiveRecord::Base data = repository.route_map_file(sha) next unless data - # TODO: Validate - YAML.safe_load(data).map do |mapping| - { - source: Regexp.new("^#{mapping['source'][1...-1]}$"), - public: mapping['public'] - } - end + Gitlab::RouteMap.new(data) + rescue Gitlab::RouteMap::FormatError + nil end end @@ -1365,10 +1361,7 @@ class Project < ActiveRecord::Base map = route_map_for_commit(commit_sha) return unless map - mapping = map.find { |mapping| path =~ mapping[:source] } - return unless mapping - - path.sub(mapping[:source], mapping[:public]) + map.public_path_for_source_path(path) end private diff --git a/app/views/projects/blob/_actions.html.haml b/app/views/projects/blob/_actions.html.haml index fbe74495e1c..6da2e4770bc 100644 --- a/app/views/projects/blob/_actions.html.haml +++ b/app/views/projects/blob/_actions.html.haml @@ -1,6 +1,6 @@ .btn-group = view_on_environment_btn(@commit.sha, @path, @environment) if @environment - + .btn-group.tree-btn-group = link_to 'Raw', namespace_project_raw_path(@project.namespace, @project, @id), class: 'btn btn-sm', target: '_blank' diff --git a/lib/gitlab/route_map.rb b/lib/gitlab/route_map.rb new file mode 100644 index 00000000000..89985d90c10 --- /dev/null +++ b/lib/gitlab/route_map.rb @@ -0,0 +1,52 @@ +module Gitlab + class RouteMap + class FormatError < StandardError; end + + def initialize(data) + begin + entries = YAML.safe_load(data) + rescue + raise FormatError, 'Route map needs to be valid YAML' + end + + raise FormatError, 'Route map needs to be an array' unless entries.is_a?(Array) + + @map = entries.map { |entry| parse_entry(entry) } + end + + def public_path_for_source_path(path) + mapping = @map.find { |mapping| path =~ mapping[:source] } + return unless mapping + + path.sub(mapping[:source], mapping[:public]) + end + + private + + def parse_entry(entry) + raise FormatError, 'Route map entry needs to be a hash' unless entry.is_a?(Hash) + raise FormatError, 'Route map entry requires a source key' unless entry.has_key?('source') + raise FormatError, 'Route map entry requires a public key' unless entry.has_key?('public') + + source_regexp = entry['source'] + public_path = entry['public'] + + unless source_regexp.start_with?('/') && source_regexp.end_with?('/') + raise FormatError, 'Route map entry source needs to start and end in a slash (/)' + end + + source_regexp = source_regexp[1...-1].gsub('\/', '/') + + begin + source_regexp = Regexp.new("^#{source_regexp}$") + rescue RegexpError => e + raise FormatError, "Route map entry source needs to be a valid regular expression: #{e}" + end + + { + source: source_regexp, + public: public_path + } + end + end +end