BigW Consortium Gitlab

url_sanitizer.rb 2.25 KB
Newer Older
1
module Gitlab
2
  class UrlSanitizer
3
    ALLOWED_SCHEMES = %w[http https ssh git].freeze
4

5
    def self.sanitize(content)
6
      regexp = URI::Parser.new.make_regexp(ALLOWED_SCHEMES)
7 8

      content.gsub(regexp) { |url| new(url).masked_url }
9 10
    rescue Addressable::URI::InvalidURIError
      content.gsub(regexp, '')
11 12
    end

James Lopez committed
13
    def self.valid?(url)
14
      return false unless url.present?
15

16
      uri = Addressable::URI.parse(url.strip)
James Lopez committed
17

18
      ALLOWED_SCHEMES.include?(uri.scheme)
James Lopez committed
19 20 21 22
    rescue Addressable::URI::InvalidURIError
      false
    end

James Lopez committed
23
    def initialize(url, credentials: nil)
24 25 26 27
      %i[user password].each do |symbol|
        credentials[symbol] = credentials[symbol].presence if credentials&.key?(symbol)
      end

James Lopez committed
28
      @credentials = credentials
29
      @url = parse_url(url)
30 31 32 33 34 35
    end

    def sanitized_url
      @sanitized_url ||= safe_url.to_s
    end

36 37
    def masked_url
      url = @url.dup
38 39
      url.password = "*****" if url.password.present?
      url.user = "*****" if url.user.present?
40 41 42
      url.to_s
    end

43
    def credentials
44
      @credentials ||= { user: @url.user.presence, password: @url.password.presence }
45 46
    end

James Lopez committed
47 48 49 50
    def full_url
      @full_url ||= generate_full_url.to_s
    end

51 52
    private

53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
    def parse_url(url)
      url             = url.to_s.strip
      match           = url.match(%r{\A(?:git|ssh|http(?:s?))\://(?:(.+)(?:@))?(.+)})
      raw_credentials = match[1] if match

      if raw_credentials.present?
        url.sub!("#{raw_credentials}@", '')

        user, password = raw_credentials.split(':')
        @credentials ||= { user: user.presence, password: password.presence }
      end

      url = Addressable::URI.parse(url)
      url.password = password if password.present?
      url.user = user if user.present?
      url
    end

James Lopez committed
71
    def generate_full_url
James Lopez committed
72
      return @url unless valid_credentials?
73

James Lopez committed
74
      @full_url = @url.dup
75

76 77
      @full_url.password = credentials[:password] if credentials[:password].present?
      @full_url.user = credentials[:user] if credentials[:user].present?
78

James Lopez committed
79 80 81
      @full_url
    end

82 83 84 85 86 87
    def safe_url
      safe_url = @url.dup
      safe_url.password = nil
      safe_url.user = nil
      safe_url
    end
James Lopez committed
88 89 90 91

    def valid_credentials?
      credentials && credentials.is_a?(Hash) && credentials.any?
    end
92
  end
93
end