Welcome to mirror list, hosted at ThFree Co, Russian Federation.

namespace_validator.rb « validators « app - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 4d99b09e98f22103fd5f7afe7823f9a3734b662b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# NamespaceValidator
#
# Custom validator for GitLab namespace values.
#
# Values are checked for formatting and exclusion from a list of reserved path
# names.
class NamespaceValidator < ActiveModel::EachValidator
  # 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[
    .well-known
    admin
    all
    assets
    ci
    dashboard
    files
    groups
    help
    hooks
    issues
    merge_requests
    new
    notes
    profile
    projects
    public
    repository
    robots.txt
    s
    search
    services
    snippets
    teams
    u
    unsubscribes
    users
    api
    autocomplete
    search
    member
    explore
    uploads
    import
    notification_settings
    abuse_reports
    invites
    help
    koding
    health_check
    jwt
    oauth
    sent_notifications
  ]).freeze

  # 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.
  #

  WILDCARD_ROUTES = Set.new(%w[tree commits wikis new edit create update logs_tree
                               preview blob blame raw files create_dir find_file
                               artifacts graphs refs badges objects folders file])

  STRICT_RESERVED = (TOP_LEVEL_ROUTES | WILDCARD_ROUTES)

  def self.valid_full_path?(full_path)
    pieces = full_path.split('/')
    first_part = pieces.first
    pieces.all? do |namespace|
      type = first_part == namespace ? :top_level : :wildcard
      valid?(namespace, type: type)
    end
  end

  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)
    else
      STRICT_RESERVED.include?(value)
    end
  end

  def self.follow_format?(value)
    value =~ Gitlab::Regex.namespace_regex
  end

  delegate :reserved?, :follow_format?, to: :class

  def validate_each(record, attribute, value)
    unless follow_format?(value)
      record.errors.add(attribute, Gitlab::Regex.namespace_regex_message)
    end

    if reserved?(value, type: validation_type(record))
      record.errors.add(attribute, "#{value} is a reserved name")
    end
  end

  def validation_type(record)
    case record
    when Group
      record.parent_id ? :wildcard : :top_level
    when Project
      :wildcard
    else
      :strict
    end
  end
end