2015-12-07 21:17:12 +00:00
|
|
|
# NamespaceValidator
|
|
|
|
#
|
|
|
|
# Custom validator for GitLab namespace values.
|
|
|
|
#
|
2015-12-07 21:29:39 +00:00
|
|
|
# Values are checked for formatting and exclusion from a list of reserved path
|
|
|
|
# names.
|
2015-12-07 21:17:12 +00:00
|
|
|
class NamespaceValidator < ActiveModel::EachValidator
|
2017-04-05 13:41:00 +00:00
|
|
|
# All routes that appear on the top level must be listed here.
|
|
|
|
# This will make sure that groups cannot be created with these names
|
|
|
|
# as these routes would be masked by the paths already in place.
|
|
|
|
#
|
|
|
|
# Example:
|
|
|
|
# /api/api-project
|
|
|
|
#
|
|
|
|
# the path `api` shouldn't be allowed because it would be masked by `api/*`
|
|
|
|
#
|
|
|
|
TOP_LEVEL_ROUTES = Set.new(%w[
|
2016-09-29 08:36:38 +00:00
|
|
|
.well-known
|
2015-12-07 21:29:39 +00:00
|
|
|
admin
|
|
|
|
all
|
|
|
|
assets
|
|
|
|
ci
|
|
|
|
dashboard
|
|
|
|
files
|
|
|
|
groups
|
|
|
|
help
|
|
|
|
hooks
|
|
|
|
issues
|
|
|
|
merge_requests
|
2016-01-08 09:19:22 +00:00
|
|
|
new
|
2015-12-07 21:29:39 +00:00
|
|
|
notes
|
|
|
|
profile
|
|
|
|
projects
|
|
|
|
public
|
|
|
|
repository
|
2016-10-11 01:58:26 +00:00
|
|
|
robots.txt
|
2015-12-07 21:29:39 +00:00
|
|
|
s
|
|
|
|
search
|
|
|
|
services
|
|
|
|
snippets
|
|
|
|
teams
|
|
|
|
u
|
|
|
|
unsubscribes
|
|
|
|
users
|
2017-04-03 12:07:15 +00:00
|
|
|
api
|
|
|
|
autocomplete
|
|
|
|
search
|
|
|
|
member
|
|
|
|
explore
|
|
|
|
uploads
|
|
|
|
import
|
|
|
|
notification_settings
|
|
|
|
abuse_reports
|
|
|
|
invites
|
|
|
|
help
|
|
|
|
koding
|
|
|
|
health_check
|
|
|
|
jwt
|
|
|
|
oauth
|
|
|
|
sent_notifications
|
2017-04-05 13:41:00 +00:00
|
|
|
]).freeze
|
2015-12-07 21:29:39 +00:00
|
|
|
|
2017-04-05 13:41:00 +00:00
|
|
|
# All project routes with wildcard argument must be listed here.
|
|
|
|
# Otherwise it can lead to routing issues when route considered as project name.
|
|
|
|
#
|
|
|
|
# Example:
|
|
|
|
# /group/project/tree/deploy_keys
|
|
|
|
#
|
|
|
|
# without tree as reserved name routing can match 'group/project' as group name,
|
|
|
|
# 'tree' as project name and 'deploy_keys' as route.
|
|
|
|
#
|
2017-04-10 17:27:19 +00:00
|
|
|
|
2017-04-05 13:41:00 +00:00
|
|
|
WILDCARD_ROUTES = Set.new(%w[tree commits wikis new edit create update logs_tree
|
|
|
|
preview blob blame raw files create_dir find_file
|
2017-04-10 17:27:19 +00:00
|
|
|
artifacts graphs refs badges objects folders file])
|
2017-03-06 18:26:58 +00:00
|
|
|
|
2017-04-11 14:21:52 +00:00
|
|
|
STRICT_RESERVED = (TOP_LEVEL_ROUTES | WILDCARD_ROUTES).freeze
|
2017-03-06 18:26:58 +00:00
|
|
|
|
2017-04-05 13:41:00 +00:00
|
|
|
def self.valid_full_path?(full_path)
|
2017-04-11 13:51:33 +00:00
|
|
|
path_segments = full_path.split('/')
|
|
|
|
root_segment = path_segments.shift
|
|
|
|
|
|
|
|
valid?(root_segment, type: :top_level) && valid_wildcard_segments?(path_segments)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.valid_wildcard_segments?(segments)
|
|
|
|
segments.all? { |segment| valid?(segment, type: :wildcard) }
|
2016-11-14 14:55:31 +00:00
|
|
|
end
|
|
|
|
|
2017-04-05 13:41:00 +00:00
|
|
|
def self.valid?(value, type: :strict)
|
|
|
|
!reserved?(value, type: type) && follow_format?(value)
|
|
|
|
end
|
|
|
|
|
|
|
|
def self.reserved?(value, type: :strict)
|
|
|
|
case type
|
|
|
|
when :wildcard
|
|
|
|
WILDCARD_ROUTES.include?(value)
|
|
|
|
when :top_level
|
|
|
|
TOP_LEVEL_ROUTES.include?(value)
|
2017-03-06 18:26:58 +00:00
|
|
|
else
|
2017-04-05 13:41:00 +00:00
|
|
|
STRICT_RESERVED.include?(value)
|
2017-03-06 18:26:58 +00:00
|
|
|
end
|
2016-11-14 14:55:31 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
def self.follow_format?(value)
|
|
|
|
value =~ Gitlab::Regex.namespace_regex
|
|
|
|
end
|
|
|
|
|
|
|
|
delegate :reserved?, :follow_format?, to: :class
|
|
|
|
|
2015-12-07 21:17:12 +00:00
|
|
|
def validate_each(record, attribute, value)
|
2016-11-14 14:55:31 +00:00
|
|
|
unless follow_format?(value)
|
2015-12-07 21:17:12 +00:00
|
|
|
record.errors.add(attribute, Gitlab::Regex.namespace_regex_message)
|
|
|
|
end
|
|
|
|
|
2017-04-05 13:41:00 +00:00
|
|
|
if reserved?(value, type: validation_type(record))
|
2015-12-07 21:17:12 +00:00
|
|
|
record.errors.add(attribute, "#{value} is a reserved name")
|
|
|
|
end
|
|
|
|
end
|
2017-04-05 13:41:00 +00:00
|
|
|
|
|
|
|
def validation_type(record)
|
|
|
|
case record
|
2017-04-11 14:21:52 +00:00
|
|
|
when Namespace
|
|
|
|
record.has_parent? ? :wildcard : :top_level
|
2017-04-05 13:41:00 +00:00
|
|
|
when Project
|
|
|
|
:wildcard
|
|
|
|
else
|
|
|
|
:strict
|
|
|
|
end
|
|
|
|
end
|
2015-12-07 21:17:12 +00:00
|
|
|
end
|