summaryrefslogtreecommitdiff
path: root/spec/validators
diff options
context:
space:
mode:
authorBob Van Landuyt <bob@gitlab.com>2017-04-10 19:27:19 +0200
committerBob Van Landuyt <bob@gitlab.com>2017-05-01 11:14:24 +0200
commite4f5b7ca2184473985ef216df676ddb737fb26af (patch)
tree3973c48d6a67f4473bdced644dfdd0b026835ad4 /spec/validators
parent74fcccaab30ac0f9e11ed9a076c008ade13a50d0 (diff)
downloadgitlab-ce-e4f5b7ca2184473985ef216df676ddb737fb26af.tar.gz
Improve detection of reserved words from routes
Diffstat (limited to 'spec/validators')
-rw-r--r--spec/validators/namespace_validator_spec.rb81
1 files changed, 67 insertions, 14 deletions
diff --git a/spec/validators/namespace_validator_spec.rb b/spec/validators/namespace_validator_spec.rb
index 4b5dd59e048..7ddce74939d 100644
--- a/spec/validators/namespace_validator_spec.rb
+++ b/spec/validators/namespace_validator_spec.rb
@@ -2,27 +2,80 @@ require 'spec_helper'
describe NamespaceValidator do
let(:validator) { described_class.new(attributes: [:path]) }
- describe 'RESERVED' do
+
+ # Pass in a full path to remove the format segment:
+ # `/ci/lint(.:format)` -> `/ci/lint`
+ def without_format(path)
+ path.split('(', 2)[0]
+ end
+
+ # Pass in a full path and get the last segment before a wildcard
+ # That's not a parameter
+ # `/*namespace_id/:project_id/builds/artifacts/*ref_name_and_path`
+ # -> 'artifacts'
+ def segment_before_last_wildcard(path)
+ path_segments = path.split('/').reject { |segment| segment.empty? }
+ last_wildcard_index = path_segments.rindex { |part| part.starts_with?('*') }
+
+ index_of_non_param_segment = last_wildcard_index - 1
+ part_before_wildcard = path_segments[index_of_non_param_segment]
+ while parameter?(part_before_wildcard)
+ index_of_non_param_segment -= 1
+ part_before_wildcard = path_segments[index_of_non_param_segment]
+ end
+
+ part_before_wildcard
+ end
+
+ def parameter?(path_segment)
+ path_segment.starts_with?(':') || path_segment.starts_with?('*')
+ end
+
+ let(:all_routes) do
+ Rails.application.routes.routes.routes.
+ map { |r| r.path.spec.to_s }
+ end
+
+ let(:routes_without_format) { all_routes.map { |path| without_format(path) } }
+
+ # Routes not starting with `/:` or `/*`
+ # all routes not starting with a param
+ let(:routes_not_starting_in_wildcard) { routes_without_format.select { |p| p !~ %r{^/[:*]} } }
+
+ # All routes that start with a namespaced path, that have 1 or more
+ # path-segments before having another wildcard parameter.
+ # - Starting with paths:
+ # - `/*namespace_id/:project_id/`
+ # - `/*namespace_id/:id/`
+ # - Followed by one or more path-parts not starting with `:` or `/`
+ # - Followed by a path-part that includes a wildcard parameter `*`
+ # At the time of writing these routes match: http://rubular.com/r/QDxulzZlxZ
+ STARTING_WITH_NAMESPACE = /^\/\*namespace_id\/:(project_)?id/
+ NON_PARAM_PARTS = /[^:*][a-z\-_\/]*/
+ ANY_OTHER_PATH_PART = /[a-z\-_\/:]*/
+ WILDCARD_SEGMENT = /\*/
+ let(:namespaced_wildcard_routes) do
+ routes_without_format.select do |p|
+ p =~ %r{#{STARTING_WITH_NAMESPACE}\/#{NON_PARAM_PARTS}\/#{ANY_OTHER_PATH_PART}#{WILDCARD_SEGMENT}}
+ end
+ end
+
+ describe 'TOP_LEVEL_ROUTES' do
it 'includes all the top level namespaces' do
- all_top_level_routes = Rails.application.routes.routes.routes.
- map { |r| r.path.spec.to_s }.
- select { |p| p !~ %r{^/[:*]} }.
- map { |p| p.split('/')[1] }.
- compact.
- map { |p| p.split('(', 2)[0] }.
- uniq
+ top_level_words = routes_not_starting_in_wildcard.
+ map { |p| p.split('/')[1] }. # Get the first part of the path
+ compact.
+ uniq
- expect(described_class::RESERVED).to include(*all_top_level_routes)
+ expect(described_class::TOP_LEVEL_ROUTES).to include(*top_level_words)
end
end
describe 'WILDCARD_ROUTES' do
it 'includes all paths that can be used after a namespace/project path' do
- all_wildcard_paths = Rails.application.routes.routes.routes.
- map { |r| r.path.spec.to_s }.
- select { |p| p =~ %r{^/\*namespace_id/:(project_)?id/[^:*]} }.
- map { |p| p.split('/')[3].split('(', 2)[0] }.
- uniq
+ all_wildcard_paths = namespaced_wildcard_routes.map do |path|
+ segment_before_last_wildcard(path)
+ end.uniq
expect(described_class::WILDCARD_ROUTES).to include(*all_wildcard_paths)
end