input_sanitizer 0.1.9 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
 - data/.github/workflows/gempush.yml +28 -0
 - data/.gitignore +2 -1
 - data/.travis.yml +4 -8
 - data/CHANGELOG +96 -0
 - data/LICENSE +201 -22
 - data/README.md +22 -3
 - data/input_sanitizer.gemspec +10 -4
 - data/lib/input_sanitizer.rb +5 -2
 - data/lib/input_sanitizer/errors.rb +142 -0
 - data/lib/input_sanitizer/extended_converters.rb +5 -52
 - data/lib/input_sanitizer/extended_converters/comma_joined_integers_converter.rb +15 -0
 - data/lib/input_sanitizer/extended_converters/comma_joined_strings_converter.rb +15 -0
 - data/lib/input_sanitizer/extended_converters/positive_integer_converter.rb +12 -0
 - data/lib/input_sanitizer/extended_converters/specific_values_converter.rb +19 -0
 - data/lib/input_sanitizer/restricted_hash.rb +49 -8
 - data/lib/input_sanitizer/v1.rb +22 -0
 - data/lib/input_sanitizer/v1/clean_field.rb +38 -0
 - data/lib/input_sanitizer/{default_converters.rb → v1/default_converters.rb} +30 -13
 - data/lib/input_sanitizer/v1/sanitizer.rb +166 -0
 - data/lib/input_sanitizer/v2.rb +13 -0
 - data/lib/input_sanitizer/v2/clean_field.rb +36 -0
 - data/lib/input_sanitizer/v2/clean_payload_collection_field.rb +41 -0
 - data/lib/input_sanitizer/v2/clean_query_collection_field.rb +40 -0
 - data/lib/input_sanitizer/v2/error_collection.rb +49 -0
 - data/lib/input_sanitizer/v2/nested_sanitizer_factory.rb +19 -0
 - data/lib/input_sanitizer/v2/payload_sanitizer.rb +130 -0
 - data/lib/input_sanitizer/v2/payload_transform.rb +42 -0
 - data/lib/input_sanitizer/v2/query_sanitizer.rb +33 -0
 - data/lib/input_sanitizer/v2/types.rb +213 -0
 - data/lib/input_sanitizer/version.rb +1 -1
 - data/spec/extended_converters/comma_joined_integers_converter_spec.rb +18 -0
 - data/spec/extended_converters/comma_joined_strings_converter_spec.rb +18 -0
 - data/spec/extended_converters/positive_integer_converter_spec.rb +18 -0
 - data/spec/extended_converters/specific_values_converter_spec.rb +27 -0
 - data/spec/restricted_hash_spec.rb +37 -7
 - data/spec/sanitizer_spec.rb +129 -26
 - data/spec/spec_helper.rb +17 -2
 - data/spec/v1/default_converters_spec.rb +141 -0
 - data/spec/v2/converters_spec.rb +174 -0
 - data/spec/v2/payload_sanitizer_spec.rb +460 -0
 - data/spec/v2/payload_transform_spec.rb +98 -0
 - data/spec/v2/query_sanitizer_spec.rb +300 -0
 - data/v2.md +52 -0
 - metadata +105 -40
 - data/lib/input_sanitizer/sanitizer.rb +0 -152
 - data/spec/default_converters_spec.rb +0 -101
 - data/spec/extended_converters_spec.rb +0 -62
 
| 
         @@ -0,0 +1,42 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'active_support/core_ext/hash/indifferent_access'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            class InputSanitizer::V2::PayloadTransform
         
     | 
| 
      
 4 
     | 
    
         
            +
              attr_reader :original_payload, :context
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
              def self.call(original_payload, context = {})
         
     | 
| 
      
 7 
     | 
    
         
            +
                new(original_payload, context).call
         
     | 
| 
      
 8 
     | 
    
         
            +
              end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              def initialize(original_payload, context = {})
         
     | 
| 
      
 11 
     | 
    
         
            +
                fail "#{self.class} is missing #transform method" unless respond_to?(:transform)
         
     | 
| 
      
 12 
     | 
    
         
            +
                @original_payload, @context = original_payload, context
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              def call
         
     | 
| 
      
 16 
     | 
    
         
            +
                transform
         
     | 
| 
      
 17 
     | 
    
         
            +
                payload
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              private
         
     | 
| 
      
 21 
     | 
    
         
            +
              def rename(from, to)
         
     | 
| 
      
 22 
     | 
    
         
            +
                if has?(from)
         
     | 
| 
      
 23 
     | 
    
         
            +
                  data = payload.delete(from)
         
     | 
| 
      
 24 
     | 
    
         
            +
                  payload[to] = data
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
              def merge_in(field, options = {})
         
     | 
| 
      
 29 
     | 
    
         
            +
                if source = payload.delete(field)
         
     | 
| 
      
 30 
     | 
    
         
            +
                  source = options[:using].call(source) if options[:using]
         
     | 
| 
      
 31 
     | 
    
         
            +
                  payload.merge!(source)
         
     | 
| 
      
 32 
     | 
    
         
            +
                end
         
     | 
| 
      
 33 
     | 
    
         
            +
              end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
              def has?(key)
         
     | 
| 
      
 36 
     | 
    
         
            +
                payload.has_key?(key)
         
     | 
| 
      
 37 
     | 
    
         
            +
              end
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
              def payload
         
     | 
| 
      
 40 
     | 
    
         
            +
                @payload ||= original_payload.with_indifferent_access
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,33 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            class InputSanitizer::V2::QuerySanitizer < InputSanitizer::V2::PayloadSanitizer
         
     | 
| 
      
 2 
     | 
    
         
            +
              def self.converters
         
     | 
| 
      
 3 
     | 
    
         
            +
                {
         
     | 
| 
      
 4 
     | 
    
         
            +
                  :integer => InputSanitizer::V2::Types::CoercingIntegerCheck.new,
         
     | 
| 
      
 5 
     | 
    
         
            +
                  :float => InputSanitizer::V2::Types::CoercingFloatCheck.new,
         
     | 
| 
      
 6 
     | 
    
         
            +
                  :string => InputSanitizer::V2::Types::StringCheck.new,
         
     | 
| 
      
 7 
     | 
    
         
            +
                  :boolean => InputSanitizer::V2::Types::CoercingBooleanCheck.new,
         
     | 
| 
      
 8 
     | 
    
         
            +
                  :datetime => InputSanitizer::V2::Types::DatetimeCheck.new,
         
     | 
| 
      
 9 
     | 
    
         
            +
                  :date => InputSanitizer::V2::Types::DatetimeCheck.new(:check_date => true),
         
     | 
| 
      
 10 
     | 
    
         
            +
                  :url => InputSanitizer::V2::Types::URLCheck.new,
         
     | 
| 
      
 11 
     | 
    
         
            +
                }
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
              initialize_types_dsl
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              def self.sort_by(allowed_values, options = {})
         
     | 
| 
      
 16 
     | 
    
         
            +
                set_keys_to_converter([:sort_by, { :allow => allowed_values }.merge(options)], InputSanitizer::V2::Types::SortByCheck.new)
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              # allow underscore cache buster by default
         
     | 
| 
      
 20 
     | 
    
         
            +
              string :_
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              private
         
     | 
| 
      
 23 
     | 
    
         
            +
              def perform_clean
         
     | 
| 
      
 24 
     | 
    
         
            +
                super
         
     | 
| 
      
 25 
     | 
    
         
            +
                @errors.each do |error|
         
     | 
| 
      
 26 
     | 
    
         
            +
                  error.field = error.field[1..-1] if error.field.start_with?('/')
         
     | 
| 
      
 27 
     | 
    
         
            +
                end
         
     | 
| 
      
 28 
     | 
    
         
            +
              end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
              def sanitizer_type
         
     | 
| 
      
 31 
     | 
    
         
            +
                :query
         
     | 
| 
      
 32 
     | 
    
         
            +
              end
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,213 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'active_support/core_ext/object/blank'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module InputSanitizer::V2::Types
         
     | 
| 
      
 4 
     | 
    
         
            +
              class IntegerCheck
         
     | 
| 
      
 5 
     | 
    
         
            +
                def call(value, options = {})
         
     | 
| 
      
 6 
     | 
    
         
            +
                  if value == nil && (options[:allow_nil] == false || options[:allow_blank] == false || options[:required] == true)
         
     | 
| 
      
 7 
     | 
    
         
            +
                    raise InputSanitizer::BlankValueError
         
     | 
| 
      
 8 
     | 
    
         
            +
                  elsif value == nil
         
     | 
| 
      
 9 
     | 
    
         
            +
                    value
         
     | 
| 
      
 10 
     | 
    
         
            +
                  else
         
     | 
| 
      
 11 
     | 
    
         
            +
                    Integer(value).tap do |integer|
         
     | 
| 
      
 12 
     | 
    
         
            +
                      raise InputSanitizer::TypeMismatchError.new(value, :integer) unless integer == value
         
     | 
| 
      
 13 
     | 
    
         
            +
                      raise InputSanitizer::ValueError.new(value, options[:minimum], options[:maximum]) if options[:minimum] && integer < options[:minimum]
         
     | 
| 
      
 14 
     | 
    
         
            +
                      raise InputSanitizer::ValueError.new(value, options[:minimum], options[:maximum]) if options[:maximum] && integer > options[:maximum]
         
     | 
| 
      
 15 
     | 
    
         
            +
                    end
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                rescue ArgumentError, TypeError
         
     | 
| 
      
 18 
     | 
    
         
            +
                  raise InputSanitizer::TypeMismatchError.new(value, :integer)
         
     | 
| 
      
 19 
     | 
    
         
            +
                end
         
     | 
| 
      
 20 
     | 
    
         
            +
              end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
              class CoercingIntegerCheck
         
     | 
| 
      
 23 
     | 
    
         
            +
                def call(value, options = {})
         
     | 
| 
      
 24 
     | 
    
         
            +
                  if value == nil || value == 'null'
         
     | 
| 
      
 25 
     | 
    
         
            +
                    if options[:allow_nil] == false || options[:allow_blank] == false || options[:required] == true
         
     | 
| 
      
 26 
     | 
    
         
            +
                      raise InputSanitizer::BlankValueError
         
     | 
| 
      
 27 
     | 
    
         
            +
                    else
         
     | 
| 
      
 28 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 29 
     | 
    
         
            +
                    end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  else
         
     | 
| 
      
 31 
     | 
    
         
            +
                    Integer(value).tap do |integer|
         
     | 
| 
      
 32 
     | 
    
         
            +
                      raise InputSanitizer::ValueError.new(value, options[:minimum], options[:maximum]) if options[:minimum] && integer < options[:minimum]
         
     | 
| 
      
 33 
     | 
    
         
            +
                      raise InputSanitizer::ValueError.new(value, options[:minimum], options[:maximum]) if options[:maximum] && integer > options[:maximum]
         
     | 
| 
      
 34 
     | 
    
         
            +
                    end
         
     | 
| 
      
 35 
     | 
    
         
            +
                  end
         
     | 
| 
      
 36 
     | 
    
         
            +
                rescue ArgumentError
         
     | 
| 
      
 37 
     | 
    
         
            +
                  raise InputSanitizer::TypeMismatchError.new(value, :integer)
         
     | 
| 
      
 38 
     | 
    
         
            +
                end
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              class FloatCheck
         
     | 
| 
      
 42 
     | 
    
         
            +
                def call(value, options = {})
         
     | 
| 
      
 43 
     | 
    
         
            +
                  if value == nil && (options[:allow_nil] == false || options[:allow_blank] == false || options[:required] == true)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    raise InputSanitizer::BlankValueError
         
     | 
| 
      
 45 
     | 
    
         
            +
                  elsif value == nil
         
     | 
| 
      
 46 
     | 
    
         
            +
                    value
         
     | 
| 
      
 47 
     | 
    
         
            +
                  else
         
     | 
| 
      
 48 
     | 
    
         
            +
                    Float(value).tap do |float|
         
     | 
| 
      
 49 
     | 
    
         
            +
                      raise InputSanitizer::TypeMismatchError.new(value, :float) unless float == value
         
     | 
| 
      
 50 
     | 
    
         
            +
                      raise InputSanitizer::ValueError.new(value, options[:minimum], options[:maximum]) if options[:minimum] && float < options[:minimum]
         
     | 
| 
      
 51 
     | 
    
         
            +
                      raise InputSanitizer::ValueError.new(value, options[:minimum], options[:maximum]) if options[:maximum] && float > options[:maximum]
         
     | 
| 
      
 52 
     | 
    
         
            +
                    end
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
                rescue ArgumentError, TypeError
         
     | 
| 
      
 55 
     | 
    
         
            +
                  raise InputSanitizer::TypeMismatchError.new(value, :float)
         
     | 
| 
      
 56 
     | 
    
         
            +
                end
         
     | 
| 
      
 57 
     | 
    
         
            +
              end
         
     | 
| 
      
 58 
     | 
    
         
            +
             
     | 
| 
      
 59 
     | 
    
         
            +
              class CoercingFloatCheck
         
     | 
| 
      
 60 
     | 
    
         
            +
                def call(value, options = {})
         
     | 
| 
      
 61 
     | 
    
         
            +
                  if value == nil || value == 'null'
         
     | 
| 
      
 62 
     | 
    
         
            +
                    if options[:allow_nil] == false || options[:allow_blank] == false || options[:required] == true
         
     | 
| 
      
 63 
     | 
    
         
            +
                      raise InputSanitizer::BlankValueError
         
     | 
| 
      
 64 
     | 
    
         
            +
                    else
         
     | 
| 
      
 65 
     | 
    
         
            +
                      nil
         
     | 
| 
      
 66 
     | 
    
         
            +
                    end
         
     | 
| 
      
 67 
     | 
    
         
            +
                  else
         
     | 
| 
      
 68 
     | 
    
         
            +
                    Float(value).tap do |float|
         
     | 
| 
      
 69 
     | 
    
         
            +
                      raise InputSanitizer::ValueError.new(value, options[:minimum], options[:maximum]) if options[:minimum] && float < options[:minimum]
         
     | 
| 
      
 70 
     | 
    
         
            +
                      raise InputSanitizer::ValueError.new(value, options[:minimum], options[:maximum]) if options[:maximum] && float > options[:maximum]
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                rescue ArgumentError
         
     | 
| 
      
 74 
     | 
    
         
            +
                  raise InputSanitizer::TypeMismatchError.new(value, :float)
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
              end
         
     | 
| 
      
 77 
     | 
    
         
            +
             
     | 
| 
      
 78 
     | 
    
         
            +
              class StringCheck
         
     | 
| 
      
 79 
     | 
    
         
            +
                def call(value, options = {})
         
     | 
| 
      
 80 
     | 
    
         
            +
                  if options[:allow] && !options[:allow].include?(value)
         
     | 
| 
      
 81 
     | 
    
         
            +
                    raise InputSanitizer::ValueNotAllowedError.new(value)
         
     | 
| 
      
 82 
     | 
    
         
            +
                  elsif value.blank? && (options[:allow_blank] == false || options[:required] == true)
         
     | 
| 
      
 83 
     | 
    
         
            +
                    raise InputSanitizer::BlankValueError
         
     | 
| 
      
 84 
     | 
    
         
            +
                  elsif options[:regexp] && options[:regexp].match(value).nil?
         
     | 
| 
      
 85 
     | 
    
         
            +
                    raise InputSanitizer::RegexpMismatchError.new
         
     | 
| 
      
 86 
     | 
    
         
            +
                  elsif value == nil && options[:allow_nil] == false
         
     | 
| 
      
 87 
     | 
    
         
            +
                    raise InputSanitizer::BlankValueError
         
     | 
| 
      
 88 
     | 
    
         
            +
                  elsif value.blank?
         
     | 
| 
      
 89 
     | 
    
         
            +
                    value
         
     | 
| 
      
 90 
     | 
    
         
            +
                  else
         
     | 
| 
      
 91 
     | 
    
         
            +
                    value.to_s.tap do |string|
         
     | 
| 
      
 92 
     | 
    
         
            +
                      raise InputSanitizer::TypeMismatchError.new(value, :string) unless string == value
         
     | 
| 
      
 93 
     | 
    
         
            +
                      raise InputSanitizer::ValueError.new(value, options[:minimum], options[:maximum]) if options[:minimum] && string.length < options[:minimum]
         
     | 
| 
      
 94 
     | 
    
         
            +
                      raise InputSanitizer::ValueError.new(value, options[:minimum], options[:maximum]) if options[:maximum] && string.length > options[:maximum]
         
     | 
| 
      
 95 
     | 
    
         
            +
                    end
         
     | 
| 
      
 96 
     | 
    
         
            +
                  end
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
              end
         
     | 
| 
      
 99 
     | 
    
         
            +
             
     | 
| 
      
 100 
     | 
    
         
            +
              class BooleanCheck
         
     | 
| 
      
 101 
     | 
    
         
            +
                def call(value, options = {})
         
     | 
| 
      
 102 
     | 
    
         
            +
                  if value == nil
         
     | 
| 
      
 103 
     | 
    
         
            +
                    raise InputSanitizer::BlankValueError
         
     | 
| 
      
 104 
     | 
    
         
            +
                  elsif [true, false].include?(value)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    value
         
     | 
| 
      
 106 
     | 
    
         
            +
                  else
         
     | 
| 
      
 107 
     | 
    
         
            +
                    raise InputSanitizer::TypeMismatchError.new(value, :boolean)
         
     | 
| 
      
 108 
     | 
    
         
            +
                  end
         
     | 
| 
      
 109 
     | 
    
         
            +
                end
         
     | 
| 
      
 110 
     | 
    
         
            +
              end
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
              class CoercingBooleanCheck
         
     | 
| 
      
 113 
     | 
    
         
            +
                def call(value, options = {})
         
     | 
| 
      
 114 
     | 
    
         
            +
                  if [true, 'true'].include?(value)
         
     | 
| 
      
 115 
     | 
    
         
            +
                    true
         
     | 
| 
      
 116 
     | 
    
         
            +
                  elsif [false, 'false'].include?(value)
         
     | 
| 
      
 117 
     | 
    
         
            +
                    false
         
     | 
| 
      
 118 
     | 
    
         
            +
                  else
         
     | 
| 
      
 119 
     | 
    
         
            +
                    raise InputSanitizer::TypeMismatchError.new(value, :boolean)
         
     | 
| 
      
 120 
     | 
    
         
            +
                  end
         
     | 
| 
      
 121 
     | 
    
         
            +
                end
         
     | 
| 
      
 122 
     | 
    
         
            +
              end
         
     | 
| 
      
 123 
     | 
    
         
            +
             
     | 
| 
      
 124 
     | 
    
         
            +
              class DatetimeCheck
         
     | 
| 
      
 125 
     | 
    
         
            +
                def initialize(options = {})
         
     | 
| 
      
 126 
     | 
    
         
            +
                  @check_date = options && options[:check_date]
         
     | 
| 
      
 127 
     | 
    
         
            +
                  @klass = @check_date ? Date : DateTime
         
     | 
| 
      
 128 
     | 
    
         
            +
                end
         
     | 
| 
      
 129 
     | 
    
         
            +
             
     | 
| 
      
 130 
     | 
    
         
            +
                def call(value, options = {})
         
     | 
| 
      
 131 
     | 
    
         
            +
                  raise InputSanitizer::TypeMismatchError.new(value, @check_date ? :date : :datetime) unless value == nil || value.is_a?(String)
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
                  if value.blank? && (options[:allow_blank] == false || options[:required] == true)
         
     | 
| 
      
 134 
     | 
    
         
            +
                    raise InputSanitizer::BlankValueError
         
     | 
| 
      
 135 
     | 
    
         
            +
                  elsif value == nil && options[:allow_nil] == false
         
     | 
| 
      
 136 
     | 
    
         
            +
                    raise InputSanitizer::BlankValueError
         
     | 
| 
      
 137 
     | 
    
         
            +
                  elsif value.blank?
         
     | 
| 
      
 138 
     | 
    
         
            +
                    value
         
     | 
| 
      
 139 
     | 
    
         
            +
                  else
         
     | 
| 
      
 140 
     | 
    
         
            +
                    @klass.parse(value).tap do |datetime|
         
     | 
| 
      
 141 
     | 
    
         
            +
                      raise InputSanitizer::ValueError.new(value, options[:minimum], options[:maximum]) if options[:minimum] && datetime < options[:minimum]
         
     | 
| 
      
 142 
     | 
    
         
            +
                      raise InputSanitizer::ValueError.new(value, options[:minimum], options[:maximum]) if options[:maximum] && datetime > options[:maximum]
         
     | 
| 
      
 143 
     | 
    
         
            +
                    end
         
     | 
| 
      
 144 
     | 
    
         
            +
                  end
         
     | 
| 
      
 145 
     | 
    
         
            +
                rescue ArgumentError, TypeError
         
     | 
| 
      
 146 
     | 
    
         
            +
                  raise InputSanitizer::TypeMismatchError.new(value, @check_date ? :date : :datetime)
         
     | 
| 
      
 147 
     | 
    
         
            +
                end
         
     | 
| 
      
 148 
     | 
    
         
            +
              end
         
     | 
| 
      
 149 
     | 
    
         
            +
             
     | 
| 
      
 150 
     | 
    
         
            +
              class URLCheck
         
     | 
| 
      
 151 
     | 
    
         
            +
                def call(value, options = {})
         
     | 
| 
      
 152 
     | 
    
         
            +
                  if value.blank? && (options[:allow_blank] == false || options[:required] == true)
         
     | 
| 
      
 153 
     | 
    
         
            +
                    raise InputSanitizer::BlankValueError
         
     | 
| 
      
 154 
     | 
    
         
            +
                  elsif value == nil && options[:allow_nil] == false
         
     | 
| 
      
 155 
     | 
    
         
            +
                    raise InputSanitizer::BlankValueError
         
     | 
| 
      
 156 
     | 
    
         
            +
                  elsif value.blank?
         
     | 
| 
      
 157 
     | 
    
         
            +
                    value
         
     | 
| 
      
 158 
     | 
    
         
            +
                  else
         
     | 
| 
      
 159 
     | 
    
         
            +
                    unless /\A#{URI.regexp(%w(http https)).to_s}\z/.match(value)
         
     | 
| 
      
 160 
     | 
    
         
            +
                      raise InputSanitizer::TypeMismatchError.new(value, :url)
         
     | 
| 
      
 161 
     | 
    
         
            +
                    end
         
     | 
| 
      
 162 
     | 
    
         
            +
                    value
         
     | 
| 
      
 163 
     | 
    
         
            +
                  end
         
     | 
| 
      
 164 
     | 
    
         
            +
                end
         
     | 
| 
      
 165 
     | 
    
         
            +
              end
         
     | 
| 
      
 166 
     | 
    
         
            +
             
     | 
| 
      
 167 
     | 
    
         
            +
              class SortByCheck
         
     | 
| 
      
 168 
     | 
    
         
            +
                def call(value, options = {})
         
     | 
| 
      
 169 
     | 
    
         
            +
                  check_options!(options)
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                  key, direction = split(value)
         
     | 
| 
      
 172 
     | 
    
         
            +
                  direction = 'asc' if direction.blank?
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
                  # special case when fallback takes care of separator sanitization e.g. custom fields
         
     | 
| 
      
 175 
     | 
    
         
            +
                  if options[:fallback] && !allowed_directions.include?(direction)
         
     | 
| 
      
 176 
     | 
    
         
            +
                    direction = 'asc'
         
     | 
| 
      
 177 
     | 
    
         
            +
                    key = value
         
     | 
| 
      
 178 
     | 
    
         
            +
                  end
         
     | 
| 
      
 179 
     | 
    
         
            +
             
     | 
| 
      
 180 
     | 
    
         
            +
                  unless valid?(key, direction, options)
         
     | 
| 
      
 181 
     | 
    
         
            +
                    raise InputSanitizer::ValueNotAllowedError.new(value)
         
     | 
| 
      
 182 
     | 
    
         
            +
                  end
         
     | 
| 
      
 183 
     | 
    
         
            +
             
     | 
| 
      
 184 
     | 
    
         
            +
                  [key, direction]
         
     | 
| 
      
 185 
     | 
    
         
            +
                end
         
     | 
| 
      
 186 
     | 
    
         
            +
             
     | 
| 
      
 187 
     | 
    
         
            +
              private
         
     | 
| 
      
 188 
     | 
    
         
            +
                def valid?(key, direction, options)
         
     | 
| 
      
 189 
     | 
    
         
            +
                  allowed_keys = options[:allow]
         
     | 
| 
      
 190 
     | 
    
         
            +
                  fallback = options[:fallback]
         
     | 
| 
      
 191 
     | 
    
         
            +
             
     | 
| 
      
 192 
     | 
    
         
            +
                  allowed_directions.include?(direction) &&
         
     | 
| 
      
 193 
     | 
    
         
            +
                    ((allowed_keys && allowed_keys.include?(key)) ||
         
     | 
| 
      
 194 
     | 
    
         
            +
                      (fallback && fallback.call(key, direction, options)))
         
     | 
| 
      
 195 
     | 
    
         
            +
                end
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
                def split(value)
         
     | 
| 
      
 198 
     | 
    
         
            +
                  head, _, tail = value.to_s.rpartition(':')
         
     | 
| 
      
 199 
     | 
    
         
            +
                  head.empty? ? [tail, head] : [head, tail]
         
     | 
| 
      
 200 
     | 
    
         
            +
                end
         
     | 
| 
      
 201 
     | 
    
         
            +
             
     | 
| 
      
 202 
     | 
    
         
            +
                def check_options!(options)
         
     | 
| 
      
 203 
     | 
    
         
            +
                  fallback = options[:fallback]
         
     | 
| 
      
 204 
     | 
    
         
            +
                  if fallback && !fallback.respond_to?(:call)
         
     | 
| 
      
 205 
     | 
    
         
            +
                    raise ArgumentError, ":fallback option must respond to method :call (proc, lambda etc)"
         
     | 
| 
      
 206 
     | 
    
         
            +
                  end
         
     | 
| 
      
 207 
     | 
    
         
            +
                end
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
                def allowed_directions
         
     | 
| 
      
 210 
     | 
    
         
            +
                  ['asc', 'desc']
         
     | 
| 
      
 211 
     | 
    
         
            +
                end
         
     | 
| 
      
 212 
     | 
    
         
            +
              end
         
     | 
| 
      
 213 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'input_sanitizer/extended_converters/comma_joined_integers_converter'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            describe InputSanitizer::CommaJoinedIntegersConverter do
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:converter) { described_class.new }
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              it "parses to array of ids" do
         
     | 
| 
      
 8 
     | 
    
         
            +
                converter.call("1,2,3,5").should eq([1, 2, 3, 5])
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              it "converts to array if given an integer" do
         
     | 
| 
      
 12 
     | 
    
         
            +
                converter.call(7).should eq([7])
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              it "raises on invalid character" do
         
     | 
| 
      
 16 
     | 
    
         
            +
                lambda { converter.call(":") }.should raise_error(InputSanitizer::ConversionError)
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'input_sanitizer/extended_converters/comma_joined_strings_converter'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            describe InputSanitizer::CommaJoinedStringsConverter do
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:converter) { described_class.new }
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              it "parses to array of ids" do
         
     | 
| 
      
 8 
     | 
    
         
            +
                converter.call("input,Sanitizer,ROCKS").should eq(["input", "Sanitizer", "ROCKS"])
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              it "allows underscores" do
         
     | 
| 
      
 12 
     | 
    
         
            +
                converter.call("input_sanitizer,rocks").should eq(["input_sanitizer", "rocks"])
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              it "raises on invalid character" do
         
     | 
| 
      
 16 
     | 
    
         
            +
                lambda { converter.call(":") }.should raise_error(InputSanitizer::ConversionError)
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,18 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'input_sanitizer/extended_converters/positive_integer_converter'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            describe InputSanitizer::PositiveIntegerConverter do
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:converter) { described_class.new }
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
              it "casts string to integer" do
         
     | 
| 
      
 8 
     | 
    
         
            +
                converter.call("3").should == 3
         
     | 
| 
      
 9 
     | 
    
         
            +
              end
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
              it "raises error if integer less than zero" do
         
     | 
| 
      
 12 
     | 
    
         
            +
                lambda { converter.call("-3") }.should raise_error(InputSanitizer::ConversionError)
         
     | 
| 
      
 13 
     | 
    
         
            +
              end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
              it "raises error if integer equals zero" do
         
     | 
| 
      
 16 
     | 
    
         
            +
                lambda { converter.call("0") }.should raise_error(InputSanitizer::ConversionError)
         
     | 
| 
      
 17 
     | 
    
         
            +
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,27 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'input_sanitizer/extended_converters/specific_values_converter'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            describe InputSanitizer::SpecificValuesConverter do
         
     | 
| 
      
 5 
     | 
    
         
            +
              let(:converter) { described_class.new(values) }
         
     | 
| 
      
 6 
     | 
    
         
            +
              let(:values) { [:a, :b] }
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              it "converts valid value to symbol" do
         
     | 
| 
      
 9 
     | 
    
         
            +
                converter.call("b").should eq(:b)
         
     | 
| 
      
 10 
     | 
    
         
            +
              end
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
              it "raises on invalid value" do
         
     | 
| 
      
 13 
     | 
    
         
            +
                lambda { converter.call("c") }.should raise_error(InputSanitizer::ConversionError)
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              it "raises on nil value" do
         
     | 
| 
      
 17 
     | 
    
         
            +
                lambda { converter.call(nil) }.should raise_error(InputSanitizer::ConversionError)
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              context "when specific values are strings" do
         
     | 
| 
      
 21 
     | 
    
         
            +
                let(:values) { ["a", "b"] }
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                it "keeps given value as string" do
         
     | 
| 
      
 24 
     | 
    
         
            +
                  converter.call("a").should eq("a")
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -1,19 +1,49 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require  
     | 
| 
      
 1 
     | 
    
         
            +
            require 'spec_helper'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
       3 
3 
     | 
    
         
             
            describe InputSanitizer::RestrictedHash do
         
     | 
| 
       4 
     | 
    
         
            -
              let(:hash) { InputSanitizer::RestrictedHash.new([:a 
     | 
| 
       5 
     | 
    
         
            -
              subject { hash }
         
     | 
| 
      
 4 
     | 
    
         
            +
              let(:hash) { InputSanitizer::RestrictedHash.new([:a]) }
         
     | 
| 
       6 
5 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
              it  
     | 
| 
       8 
     | 
    
         
            -
                lambda{hash[: 
     | 
| 
      
 6 
     | 
    
         
            +
              it 'does not allow bad keys' do
         
     | 
| 
      
 7 
     | 
    
         
            +
                lambda{ hash[:b] }.should raise_error(InputSanitizer::KeyNotAllowedError)
         
     | 
| 
       9 
8 
     | 
    
         
             
              end
         
     | 
| 
       10 
9 
     | 
    
         | 
| 
       11 
     | 
    
         
            -
              it  
     | 
| 
      
 10 
     | 
    
         
            +
              it 'does allow correct keys' do
         
     | 
| 
       12 
11 
     | 
    
         
             
                hash[:a].should be_nil
         
     | 
| 
       13 
12 
     | 
    
         
             
              end
         
     | 
| 
       14 
13 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
              it  
     | 
| 
      
 14 
     | 
    
         
            +
              it 'returns value for correct key' do
         
     | 
| 
       16 
15 
     | 
    
         
             
                hash[:a] = 'stuff'
         
     | 
| 
       17 
16 
     | 
    
         
             
                hash[:a].should == 'stuff'
         
     | 
| 
       18 
17 
     | 
    
         
             
              end
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
              it 'allows to set value for a new key' do
         
     | 
| 
      
 20 
     | 
    
         
            +
                hash[:b] = 'other stuff'
         
     | 
| 
      
 21 
     | 
    
         
            +
                hash[:b].should == 'other stuff'
         
     | 
| 
      
 22 
     | 
    
         
            +
                hash.key_allowed?(:b).should be_truthy
         
     | 
| 
      
 23 
     | 
    
         
            +
              end
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
              it 'adds new allowed keys after `transform_keys` is done' do
         
     | 
| 
      
 26 
     | 
    
         
            +
                hash[:a] = 'stuff'
         
     | 
| 
      
 27 
     | 
    
         
            +
                hash.transform_keys! { |key| key.to_s }
         
     | 
| 
      
 28 
     | 
    
         
            +
                hash['a'].should == 'stuff'
         
     | 
| 
      
 29 
     | 
    
         
            +
                hash.key_allowed?('a').should be_truthy
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
              it 'removes previous allowed keys after `transform_keys` is done' do
         
     | 
| 
      
 33 
     | 
    
         
            +
                hash[:a] = 'stuff'
         
     | 
| 
      
 34 
     | 
    
         
            +
                hash.transform_keys! { |key| key.to_s }
         
     | 
| 
      
 35 
     | 
    
         
            +
                lambda{ hash[:a] }.should raise_error(InputSanitizer::KeyNotAllowedError)
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              it 'updates allowed keys on merge!' do
         
     | 
| 
      
 39 
     | 
    
         
            +
                merge_hash = { merged: '1' }
         
     | 
| 
      
 40 
     | 
    
         
            +
                hash.merge!(merge_hash)
         
     | 
| 
      
 41 
     | 
    
         
            +
                hash.key_allowed?(:merged).should be_truthy
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              it 'updates allowed keys on merge' do
         
     | 
| 
      
 45 
     | 
    
         
            +
                merge_hash = { merged: '1' }
         
     | 
| 
      
 46 
     | 
    
         
            +
                new_hash = hash.merge(some_key: merge_hash)
         
     | 
| 
      
 47 
     | 
    
         
            +
                new_hash.key_allowed?(:some_key).should be_truthy
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
       19 
49 
     | 
    
         
             
            end
         
     | 
    
        data/spec/sanitizer_spec.rb
    CHANGED
    
    | 
         @@ -1,11 +1,22 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'spec_helper'
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            class NestedSanitizer < InputSanitizer::Sanitizer
         
     | 
| 
      
 4 
     | 
    
         
            +
              integer :foo
         
     | 
| 
      
 5 
     | 
    
         
            +
            end
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
       3 
7 
     | 
    
         
             
            class BasicSanitizer < InputSanitizer::Sanitizer
         
     | 
| 
       4 
8 
     | 
    
         
             
              string :x, :y, :z
         
     | 
| 
      
 9 
     | 
    
         
            +
              integer :namespaced, :namespace => :value
         
     | 
| 
      
 10 
     | 
    
         
            +
              integer :array, :collection => true
         
     | 
| 
      
 11 
     | 
    
         
            +
              integer :namespaced_array, :collection => true, :namespace => :value
         
     | 
| 
       5 
12 
     | 
    
         
             
              integer :num
         
     | 
| 
       6 
13 
     | 
    
         
             
              date :birthday
         
     | 
| 
       7 
14 
     | 
    
         
             
              time :updated_at
         
     | 
| 
       8 
15 
     | 
    
         
             
              custom :cust1, :cust2, :converter => lambda { |v| v.reverse }
         
     | 
| 
      
 16 
     | 
    
         
            +
              nested :stuff, :sanitizer => NestedSanitizer, :collection => true, :namespace => :nested
         
     | 
| 
      
 17 
     | 
    
         
            +
              custom :custom3, :provide => :num, :converter => lambda { |v, num|
         
     | 
| 
      
 18 
     | 
    
         
            +
                num == 1 ? v.reverse : v
         
     | 
| 
      
 19 
     | 
    
         
            +
              }
         
     | 
| 
       9 
20 
     | 
    
         
             
            end
         
     | 
| 
       10 
21 
     | 
    
         | 
| 
       11 
22 
     | 
    
         
             
            class BrokenCustomSanitizer < InputSanitizer::Sanitizer
         
     | 
| 
         @@ -28,12 +39,17 @@ class RequiredCustom < BasicSanitizer 
     | 
|
| 
       28 
39 
     | 
    
         
             
              custom :c1, :required => true, :converter => lambda { |v| v }
         
     | 
| 
       29 
40 
     | 
    
         
             
            end
         
     | 
| 
       30 
41 
     | 
    
         | 
| 
      
 42 
     | 
    
         
            +
            class DefaultParameters < BasicSanitizer
         
     | 
| 
      
 43 
     | 
    
         
            +
              integer :funky_number, :default => 5
         
     | 
| 
      
 44 
     | 
    
         
            +
              custom :fixed_stuff, :converter => lambda {|v| v }, :default => "default string"
         
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     | 
| 
      
 46 
     | 
    
         
            +
             
     | 
| 
       31 
47 
     | 
    
         
             
            describe InputSanitizer::Sanitizer do
         
     | 
| 
       32 
48 
     | 
    
         
             
              let(:sanitizer) { BasicSanitizer.new(@params) }
         
     | 
| 
       33 
49 
     | 
    
         | 
| 
       34 
50 
     | 
    
         
             
              describe ".clean" do
         
     | 
| 
       35 
51 
     | 
    
         
             
                it "returns cleaned data" do
         
     | 
| 
       36 
     | 
    
         
            -
                  clean_data =  
     | 
| 
      
 52 
     | 
    
         
            +
                  clean_data = double
         
     | 
| 
       37 
53 
     | 
    
         
             
                  BasicSanitizer.any_instance.should_receive(:cleaned).and_return(clean_data)
         
     | 
| 
       38 
54 
     | 
    
         
             
                  BasicSanitizer.clean({}).should be(clean_data)
         
     | 
| 
       39 
55 
     | 
    
         
             
                end
         
     | 
| 
         @@ -57,6 +73,12 @@ describe InputSanitizer::Sanitizer do 
     | 
|
| 
       57 
73 
     | 
    
         
             
                  cleaned.should_not have_key(:d)
         
     | 
| 
       58 
74 
     | 
    
         
             
                end
         
     | 
| 
       59 
75 
     | 
    
         | 
| 
      
 76 
     | 
    
         
            +
                it "does not include ommited fields" do
         
     | 
| 
      
 77 
     | 
    
         
            +
                  @params = { "x" => 1, "z" => 3 }
         
     | 
| 
      
 78 
     | 
    
         
            +
             
     | 
| 
      
 79 
     | 
    
         
            +
                  cleaned.should_not have_key(:y)
         
     | 
| 
      
 80 
     | 
    
         
            +
                end
         
     | 
| 
      
 81 
     | 
    
         
            +
             
     | 
| 
       60 
82 
     | 
    
         
             
                it "freezes cleaned hash" do
         
     | 
| 
       61 
83 
     | 
    
         
             
                  @params = {}
         
     | 
| 
       62 
84 
     | 
    
         | 
| 
         @@ -83,6 +105,30 @@ describe InputSanitizer::Sanitizer do 
     | 
|
| 
       83 
105 
     | 
    
         
             
                  cleaned.should_not have_key(:d)
         
     | 
| 
       84 
106 
     | 
    
         
             
                end
         
     | 
| 
       85 
107 
     | 
    
         | 
| 
      
 108 
     | 
    
         
            +
                it "preserves namespace" do
         
     | 
| 
      
 109 
     | 
    
         
            +
                  value = { :value => 5 }
         
     | 
| 
      
 110 
     | 
    
         
            +
                  @params = { :namespaced => value }
         
     | 
| 
      
 111 
     | 
    
         
            +
             
     | 
| 
      
 112 
     | 
    
         
            +
                  cleaned[:namespaced].should eq(value)
         
     | 
| 
      
 113 
     | 
    
         
            +
                end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
                it "maps values for collection fields" do
         
     | 
| 
      
 116 
     | 
    
         
            +
                  numbers = [3, 5, 6]
         
     | 
| 
      
 117 
     | 
    
         
            +
                  @params = { :array => numbers }
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                  cleaned[:array].should eq(numbers)
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                it "maps values for collection fields with namespace" do
         
     | 
| 
      
 123 
     | 
    
         
            +
                  numbers = [
         
     | 
| 
      
 124 
     | 
    
         
            +
                    { :value => 2 },
         
     | 
| 
      
 125 
     | 
    
         
            +
                    { :value => 5 }
         
     | 
| 
      
 126 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 127 
     | 
    
         
            +
                  @params = { :namespaced_array => numbers }
         
     | 
| 
      
 128 
     | 
    
         
            +
             
     | 
| 
      
 129 
     | 
    
         
            +
                  cleaned[:namespaced_array].should eq(numbers)
         
     | 
| 
      
 130 
     | 
    
         
            +
                end
         
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
       86 
132 
     | 
    
         
             
                it "silently discards cast errors" do
         
     | 
| 
       87 
133 
     | 
    
         
             
                  @params = {:num => "f"}
         
     | 
| 
       88 
134 
     | 
    
         | 
| 
         @@ -95,7 +141,7 @@ describe InputSanitizer::Sanitizer do 
     | 
|
| 
       95 
141 
     | 
    
         | 
| 
       96 
142 
     | 
    
         
             
                  cleaned.should have_key(:num)
         
     | 
| 
       97 
143 
     | 
    
         
             
                  cleaned[:num].should == 23
         
     | 
| 
       98 
     | 
    
         
            -
                  cleaned[:is_nice].should  
     | 
| 
      
 144 
     | 
    
         
            +
                  cleaned[:is_nice].should eq(false)
         
     | 
| 
       99 
145 
     | 
    
         
             
                end
         
     | 
| 
       100 
146 
     | 
    
         | 
| 
       101 
147 
     | 
    
         
             
                it "overrides inherited fields" do
         
     | 
| 
         @@ -106,6 +152,32 @@ describe InputSanitizer::Sanitizer do 
     | 
|
| 
       106 
152 
     | 
    
         
             
                  cleaned[:is_nice].should == 42
         
     | 
| 
       107 
153 
     | 
    
         
             
                end
         
     | 
| 
       108 
154 
     | 
    
         | 
| 
      
 155 
     | 
    
         
            +
                context "when sanitizer is initialized with default values" do
         
     | 
| 
      
 156 
     | 
    
         
            +
                  context "when paremeters are not overwriten" do
         
     | 
| 
      
 157 
     | 
    
         
            +
                    let(:sanitizer) { DefaultParameters.new({}) }
         
     | 
| 
      
 158 
     | 
    
         
            +
             
     | 
| 
      
 159 
     | 
    
         
            +
                    it "returns default value for non custom key" do
         
     | 
| 
      
 160 
     | 
    
         
            +
                      sanitizer.cleaned[:funky_number].should == 5
         
     | 
| 
      
 161 
     | 
    
         
            +
                    end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                    it "returns default value for custom key" do
         
     | 
| 
      
 164 
     | 
    
         
            +
                      sanitizer.cleaned[:fixed_stuff].should == "default string"
         
     | 
| 
      
 165 
     | 
    
         
            +
                    end
         
     | 
| 
      
 166 
     | 
    
         
            +
                  end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
                  context "when parameters are overwriten" do
         
     | 
| 
      
 169 
     | 
    
         
            +
                    let(:sanitizer) { DefaultParameters.new({ :funky_number => 2, :fixed_stuff => "fixed" }) }
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                    it "returns default value for non custom key" do
         
     | 
| 
      
 172 
     | 
    
         
            +
                      sanitizer.cleaned[:funky_number].should == 2
         
     | 
| 
      
 173 
     | 
    
         
            +
                    end
         
     | 
| 
      
 174 
     | 
    
         
            +
             
     | 
| 
      
 175 
     | 
    
         
            +
                    it "returns default value for custom key" do
         
     | 
| 
      
 176 
     | 
    
         
            +
                      sanitizer.cleaned[:fixed_stuff].should == "fixed"
         
     | 
| 
      
 177 
     | 
    
         
            +
                    end
         
     | 
| 
      
 178 
     | 
    
         
            +
                  end
         
     | 
| 
      
 179 
     | 
    
         
            +
                end
         
     | 
| 
      
 180 
     | 
    
         
            +
             
     | 
| 
       109 
181 
     | 
    
         
             
              end
         
     | 
| 
       110 
182 
     | 
    
         | 
| 
       111 
183 
     | 
    
         
             
              describe ".custom" do
         
     | 
| 
         @@ -120,9 +192,53 @@ describe InputSanitizer::Sanitizer do 
     | 
|
| 
       120 
192 
     | 
    
         
             
                end
         
     | 
| 
       121 
193 
     | 
    
         | 
| 
       122 
194 
     | 
    
         
             
                it "raises an error when converter is not defined" do
         
     | 
| 
       123 
     | 
    
         
            -
                   
     | 
| 
      
 195 
     | 
    
         
            +
                  lambda do
         
     | 
| 
       124 
196 
     | 
    
         
             
                    BrokenCustomSanitizer.custom(:x)
         
     | 
| 
       125 
     | 
    
         
            -
                  end. 
     | 
| 
      
 197 
     | 
    
         
            +
                  end.should raise_error
         
     | 
| 
      
 198 
     | 
    
         
            +
                end
         
     | 
| 
      
 199 
     | 
    
         
            +
             
     | 
| 
      
 200 
     | 
    
         
            +
                it "provides the converter with requested value" do
         
     | 
| 
      
 201 
     | 
    
         
            +
                  @params = { :custom3 => 'three', :num => 1 }
         
     | 
| 
      
 202 
     | 
    
         
            +
                  cleaned.should have_key(:custom3)
         
     | 
| 
      
 203 
     | 
    
         
            +
                  cleaned.should have_key(:num)
         
     | 
| 
      
 204 
     | 
    
         
            +
                  cleaned[:custom3].should eq('eerht')
         
     | 
| 
      
 205 
     | 
    
         
            +
                  cleaned[:num].should eq(1)
         
     | 
| 
      
 206 
     | 
    
         
            +
                end
         
     | 
| 
      
 207 
     | 
    
         
            +
              end
         
     | 
| 
      
 208 
     | 
    
         
            +
             
     | 
| 
      
 209 
     | 
    
         
            +
              describe ".nested" do
         
     | 
| 
      
 210 
     | 
    
         
            +
                let(:sanitizer) { BasicSanitizer.new(@params) }
         
     | 
| 
      
 211 
     | 
    
         
            +
                let(:cleaned) { sanitizer.cleaned }
         
     | 
| 
      
 212 
     | 
    
         
            +
             
     | 
| 
      
 213 
     | 
    
         
            +
                it "sanitizes nested values" do
         
     | 
| 
      
 214 
     | 
    
         
            +
                  nested = [
         
     | 
| 
      
 215 
     | 
    
         
            +
                    { :nested => { :foo => "5" } },
         
     | 
| 
      
 216 
     | 
    
         
            +
                    { :nested => { :foo => 8 } },
         
     | 
| 
      
 217 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 218 
     | 
    
         
            +
                  @params = { :stuff => nested }
         
     | 
| 
      
 219 
     | 
    
         
            +
             
     | 
| 
      
 220 
     | 
    
         
            +
                  expected = [
         
     | 
| 
      
 221 
     | 
    
         
            +
                    { :nested => { :foo => 5 } },
         
     | 
| 
      
 222 
     | 
    
         
            +
                    { :nested => { :foo => 8 } },
         
     | 
| 
      
 223 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 224 
     | 
    
         
            +
                  cleaned[:stuff].should eq(expected)
         
     | 
| 
      
 225 
     | 
    
         
            +
                end
         
     | 
| 
      
 226 
     | 
    
         
            +
             
     | 
| 
      
 227 
     | 
    
         
            +
                it "propagates errors" do
         
     | 
| 
      
 228 
     | 
    
         
            +
                  nested = [ { :nested => { :foo => "INVALID" } } ]
         
     | 
| 
      
 229 
     | 
    
         
            +
                  @params = { :stuff => nested }
         
     | 
| 
      
 230 
     | 
    
         
            +
             
     | 
| 
      
 231 
     | 
    
         
            +
                  sanitizer.should_not be_valid
         
     | 
| 
      
 232 
     | 
    
         
            +
                end
         
     | 
| 
      
 233 
     | 
    
         
            +
             
     | 
| 
      
 234 
     | 
    
         
            +
                it "returns an error when given a nil for a nested value" do
         
     | 
| 
      
 235 
     | 
    
         
            +
                  @params = { :stuff => nil }
         
     | 
| 
      
 236 
     | 
    
         
            +
                  sanitizer.should_not be_valid
         
     | 
| 
      
 237 
     | 
    
         
            +
                end
         
     | 
| 
      
 238 
     | 
    
         
            +
             
     | 
| 
      
 239 
     | 
    
         
            +
                it "returns an error when given a string for a nested value" do
         
     | 
| 
      
 240 
     | 
    
         
            +
                  @params = { :stuff => 'nope' }
         
     | 
| 
      
 241 
     | 
    
         
            +
                  sanitizer.should_not be_valid
         
     | 
| 
       126 
242 
     | 
    
         
             
                end
         
     | 
| 
       127 
243 
     | 
    
         
             
              end
         
     | 
| 
       128 
244 
     | 
    
         | 
| 
         @@ -131,43 +247,25 @@ describe InputSanitizer::Sanitizer do 
     | 
|
| 
       131 
247 
     | 
    
         | 
| 
       132 
248 
     | 
    
         
             
                it "includes :integer type" do
         
     | 
| 
       133 
249 
     | 
    
         
             
                  sanitizer.converters.should have_key(:integer)
         
     | 
| 
       134 
     | 
    
         
            -
                  sanitizer.converters[:integer].should be_a(InputSanitizer::IntegerConverter)
         
     | 
| 
      
 250 
     | 
    
         
            +
                  sanitizer.converters[:integer].should be_a(InputSanitizer::V1::IntegerConverter)
         
     | 
| 
       135 
251 
     | 
    
         
             
                end
         
     | 
| 
       136 
252 
     | 
    
         | 
| 
       137 
253 
     | 
    
         
             
                it "includes :string type" do
         
     | 
| 
       138 
254 
     | 
    
         
             
                  sanitizer.converters.should have_key(:string)
         
     | 
| 
       139 
     | 
    
         
            -
                  sanitizer.converters[:string].should be_a(InputSanitizer::StringConverter)
         
     | 
| 
      
 255 
     | 
    
         
            +
                  sanitizer.converters[:string].should be_a(InputSanitizer::V1::StringConverter)
         
     | 
| 
       140 
256 
     | 
    
         
             
                end
         
     | 
| 
       141 
257 
     | 
    
         | 
| 
       142 
258 
     | 
    
         
             
                it "includes :date type" do
         
     | 
| 
       143 
259 
     | 
    
         
             
                  sanitizer.converters.should have_key(:date)
         
     | 
| 
       144 
     | 
    
         
            -
                  sanitizer.converters[:date].should be_a(InputSanitizer::DateConverter)
         
     | 
| 
      
 260 
     | 
    
         
            +
                  sanitizer.converters[:date].should be_a(InputSanitizer::V1::DateConverter)
         
     | 
| 
       145 
261 
     | 
    
         
             
                end
         
     | 
| 
       146 
262 
     | 
    
         | 
| 
       147 
263 
     | 
    
         
             
                it "includes :boolean type" do
         
     | 
| 
       148 
264 
     | 
    
         
             
                  sanitizer.converters.should have_key(:boolean)
         
     | 
| 
       149 
     | 
    
         
            -
                  sanitizer.converters[:boolean].should be_a(InputSanitizer::BooleanConverter)
         
     | 
| 
      
 265 
     | 
    
         
            +
                  sanitizer.converters[:boolean].should be_a(InputSanitizer::V1::BooleanConverter)
         
     | 
| 
       150 
266 
     | 
    
         
             
                end
         
     | 
| 
       151 
267 
     | 
    
         
             
              end
         
     | 
| 
       152 
268 
     | 
    
         | 
| 
       153 
     | 
    
         
            -
              describe '.extract_options' do
         
     | 
| 
       154 
     | 
    
         
            -
             
     | 
| 
       155 
     | 
    
         
            -
                it "extracts hash from array if is last" do
         
     | 
| 
       156 
     | 
    
         
            -
                  options = { :a => 1}
         
     | 
| 
       157 
     | 
    
         
            -
                  array = [1,2, options]
         
     | 
| 
       158 
     | 
    
         
            -
                  BasicSanitizer.extract_options(array).should == options
         
     | 
| 
       159 
     | 
    
         
            -
                  array.should == [1,2, options]
         
     | 
| 
       160 
     | 
    
         
            -
                end
         
     | 
| 
       161 
     | 
    
         
            -
             
     | 
| 
       162 
     | 
    
         
            -
                it "does not extract the last element if not a hash and returns default empty hash" do
         
     | 
| 
       163 
     | 
    
         
            -
                  array = [1,2]
         
     | 
| 
       164 
     | 
    
         
            -
                  BasicSanitizer.extract_options(array).should_not == 2
         
     | 
| 
       165 
     | 
    
         
            -
                  BasicSanitizer.extract_options(array).should == {}
         
     | 
| 
       166 
     | 
    
         
            -
                  array.should == [1,2]
         
     | 
| 
       167 
     | 
    
         
            -
                end
         
     | 
| 
       168 
     | 
    
         
            -
             
     | 
| 
       169 
     | 
    
         
            -
              end
         
     | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
269 
     | 
    
         
             
              describe '.extract_options!' do
         
     | 
| 
       172 
270 
     | 
    
         | 
| 
       173 
271 
     | 
    
         
             
                it "extracts hash from array if is last" do
         
     | 
| 
         @@ -234,4 +332,9 @@ describe InputSanitizer::Sanitizer do 
     | 
|
| 
       234 
332 
     | 
    
         
             
                  error[:field].should == :c1
         
     | 
| 
       235 
333 
     | 
    
         
             
                end
         
     | 
| 
       236 
334 
     | 
    
         
             
              end
         
     | 
| 
      
 335 
     | 
    
         
            +
             
     | 
| 
      
 336 
     | 
    
         
            +
              it "is valid when given extra params" do
         
     | 
| 
      
 337 
     | 
    
         
            +
                @params = { :extra => 'test' }
         
     | 
| 
      
 338 
     | 
    
         
            +
                sanitizer.should be_valid
         
     | 
| 
      
 339 
     | 
    
         
            +
              end
         
     | 
| 
       237 
340 
     | 
    
         
             
            end
         
     |