diff options
Diffstat (limited to 'lib/gitlab/config/entry/validators.rb')
-rw-r--r-- | lib/gitlab/config/entry/validators.rb | 144 |
1 files changed, 132 insertions, 12 deletions
diff --git a/lib/gitlab/config/entry/validators.rb b/lib/gitlab/config/entry/validators.rb index 25bfa50f829..6796fcce75f 100644 --- a/lib/gitlab/config/entry/validators.rb +++ b/lib/gitlab/config/entry/validators.rb @@ -15,6 +15,17 @@ module Gitlab end end + class DisallowedKeysValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + present_keys = value.try(:keys).to_a & options[:in] + + if present_keys.any? + record.errors.add(attribute, "contains disallowed keys: " + + present_keys.join(', ')) + end + end + end + class AllowedValuesValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) unless options[:in].include?(value.to_s) @@ -25,10 +36,10 @@ module Gitlab class AllowedArrayValuesValidator < ActiveModel::EachValidator def validate_each(record, attribute, value) - unkown_values = value - options[:in] - unless unkown_values.empty? + unknown_values = value - options[:in] + unless unknown_values.empty? record.errors.add(attribute, "contains unknown values: " + - unkown_values.join(', ')) + unknown_values.join(', ')) end end end @@ -43,6 +54,14 @@ module Gitlab end end + class ArrayOrStringValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + unless value.is_a?(Array) || value.is_a?(String) + record.errors.add(attribute, 'should be an array or a string') + end + end + end + class BooleanValidator < ActiveModel::EachValidator include LegacyValidationHelpers @@ -118,19 +137,21 @@ module Gitlab end end + protected + + def fallback + false + end + private - def look_like_regexp?(value) - value.is_a?(String) && value.start_with?('/') && - value.end_with?('/') + def matches_syntax?(value) + Gitlab::UntrustedRegexp::RubySyntax.matches_syntax?(value) end def validate_regexp(value) - look_like_regexp?(value) && - Regexp.new(value.to_s[1...-1]) && - true - rescue RegexpError - false + matches_syntax?(value) && + Gitlab::UntrustedRegexp::RubySyntax.valid?(value, fallback: fallback) end end @@ -149,8 +170,16 @@ module Gitlab def validate_string_or_regexp(value) return false unless value.is_a?(String) - return validate_regexp(value) if look_like_regexp?(value) + return validate_regexp(value) if matches_syntax?(value) + + true + end + end + class ArrayOfStringsOrRegexpsWithFallbackValidator < ArrayOfStringsOrRegexpsValidator + protected + + def fallback true end end @@ -190,6 +219,97 @@ module Gitlab end end end + + class PortNamePresentAndUniqueValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + return unless value.is_a?(Array) + + ports_size = value.count + return if ports_size <= 1 + + named_ports = value.select { |e| e.is_a?(Hash) }.map { |e| e[:name] }.compact.map(&:downcase) + + if ports_size != named_ports.size + record.errors.add(attribute, 'when there is more than one port, a unique name should be added') + end + + if ports_size != named_ports.uniq.size + record.errors.add(attribute, 'each port name must be different') + end + end + end + + class PortUniqueValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + value = ports(value) + return unless value.is_a?(Array) + + ports_size = value.count + return if ports_size <= 1 + + if transform_ports(value).size != ports_size + record.errors.add(attribute, 'each port number can only be referenced once') + end + end + + private + + def ports(current_data) + current_data + end + + def transform_ports(raw_ports) + raw_ports.map do |port| + case port + when Integer + port + when Hash + port[:number] + end + end.uniq + end + end + + class JobPortUniqueValidator < PortUniqueValidator + private + + def ports(current_data) + return unless current_data.is_a?(Hash) + + (image_ports(current_data) + services_ports(current_data)).compact + end + + def image_ports(current_data) + return [] unless current_data[:image].is_a?(Hash) + + current_data.dig(:image, :ports).to_a + end + + def services_ports(current_data) + current_data.dig(:services).to_a.flat_map { |service| service.is_a?(Hash) ? service[:ports] : nil } + end + end + + class ServicesWithPortsAliasUniqueValidator < ActiveModel::EachValidator + def validate_each(record, attribute, value) + current_aliases = aliases(value) + return if current_aliases.empty? + + unless aliases_unique?(current_aliases) + record.errors.add(:config, 'alias must be unique in services with ports') + end + end + + private + + def aliases(value) + value.select { |s| s.is_a?(Hash) && s[:ports] }.pluck(:alias) # rubocop:disable CodeReuse/ActiveRecord + end + + def aliases_unique?(aliases) + aliases.size == aliases.uniq.size + end + end end end end |