debian-mirror-gitlab/lib/sbom/package_url/argument_validator.rb
2023-01-12 18:35:48 +00:00

90 lines
2.2 KiB
Ruby

# frozen_string_literal: true
module Sbom
class PackageUrl
class ArgumentValidator
QUALIFIER_KEY_REGEXP = /^[A-Za-z\d._-]+$/.freeze
START_WITH_NUMBER_REGEXP = /^\d/.freeze
def initialize(package)
@type = package.type
@namespace = package.namespace
@name = package.name
@version = package.version
@qualifiers = package.qualifiers
@errors = []
end
def validate!
validate_type
validate_name
validate_qualifiers
validate_by_type
raise ArgumentError, formatted_errors if invalid?
end
private
def invalid?
errors.present?
end
attr_reader :type, :namespace, :name, :version, :qualifiers, :errors
def formatted_errors
errors.join(', ')
end
def validate_type
errors.push('Type is required') if type.blank?
end
def validate_name
errors.push('Name is required') if name.blank?
end
def validate_qualifiers
return if qualifiers.nil?
keys = qualifiers.keys
errors.push('Qualifier keys must be unique') unless keys.uniq.size == keys.size
keys.each do |key|
errors.push(key_error(key, 'contains illegal characters')) unless key.match?(QUALIFIER_KEY_REGEXP)
errors.push(key_error(key, 'may not start with a number')) if key.match?(START_WITH_NUMBER_REGEXP)
end
end
def key_error(key, text)
"Qualifier key `#{key}` #{text}"
end
def validate_by_type
case type
when 'conan'
validate_conan
when 'cran'
validate_cran
when 'swift'
validate_swift
end
end
def validate_conan
return unless namespace.blank? ^ (qualifiers.nil? || qualifiers.exclude?('channel'))
errors.push('Conan packages require the channel be present if published in a namespace and vice-versa')
end
def validate_cran
errors.push('Cran packages require a version') if version.blank?
end
def validate_swift
errors.push('Swift packages require a namespace') if namespace.blank?
errors.push('Swift packages require a version') if version.blank?
end
end
end
end