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

argument_validator.rb « package_url « sbom « lib - gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: 639ee9f89b63c49f1ffc29826a18a6bb0a0b3511 (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
# 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