felipead/http-token-auth

View on GitHub
lib/http/token_auth/challenge.rb

Summary

Maintainability
A
0 mins
Test Coverage
module HTTP
  module TokenAuth
    class ChallengeArgumentError < StandardError
    end

    class Challenge
      attr_reader :realm, :supported_coverages, :timestamp

      def initialize(realm:, supported_coverages: nil, timestamp: nil)
        @realm = realm
        @supported_coverages = supported_coverages_or_default(supported_coverages)
        @timestamp = timestamp
        validate_itself
      end

      def to_header
        attributes = []
        attributes << %(realm="#{@realm}")
        attributes << %(coverage="#{coverage_string}")
        unless supported_coverages.include?(:none)
          attributes << %(timestamp="#{@timestamp}")
        end
        "Token #{attributes.join(', ')}"
      end

      private

      def supported_coverages_or_default(list)
        return [:base] if list.nil? || list.empty?
        list
      end

      def validate_itself
        must_have_realm
        supported_coverages_must_be_consistent
        must_have_timestamp unless supported_coverages.include?(:none)
      end

      def must_have_realm
        raise ChallengeArgumentError, '"realm" is missing' if @realm.nil? || @realm.empty?
      end

      def must_have_timestamp
        raise ChallengeArgumentError, '"timestamp" is missing' if @timestamp.nil?
      end

      def supported_coverages_must_be_consistent
        return unless supported_coverages.include?(:none) && supported_coverages.size > 1
        raise ChallengeArgumentError, 'coverage "none" cannot be combined with other coverages'
      end

      def coverage_string
        @supported_coverages.map do |coverage|
          coverage_name(coverage)
        end.join(' ')
      end

      def coverage_name(coverage)
        case coverage
        when :none then 'none'
        when :base then 'base'
        when :base_body_sha_256 then 'base+body-sha-256'
        end
      end
    end
  end
end