input_sanitizer 0.1.10 → 0.2.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/.travis.yml +1 -1
- data/lib/input_sanitizer/default_converters.rb +13 -3
- data/lib/input_sanitizer/sanitizer.rb +35 -5
- data/lib/input_sanitizer/version.rb +1 -1
- data/spec/default_converters_spec.rb +19 -1
- data/spec/sanitizer_spec.rb +83 -1
- data/spec/spec_helper.rb +4 -2
- metadata +11 -17
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 80975685ea36b822133f114e4f25a86795ab1a84
|
4
|
+
data.tar.gz: fe52c7a9f8039a61e247cc7634a93d176de4ed32
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3fd6f2abb6f51ddfc1e161568515dcb40800f3eb7c7a28962253040d1aa37052de7b3e15f1f6b0b5b739a54276b1d76b7f66f98289ad4052afb2fd84b264ddbb
|
7
|
+
data.tar.gz: cfc6ea3add9b7a3d9089e30830e53e1ffa00ec12daacb0d0ced5c6c8eedc05d22d112a2c29c3617c886ee57dd5559bea455901384b18ad78f7d437c681f9d38d
|
data/.travis.yml
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'time'
|
2
|
+
require 'date'
|
2
3
|
|
3
4
|
module InputSanitizer
|
4
5
|
class ConversionError < Exception
|
@@ -32,11 +33,18 @@ module InputSanitizer
|
|
32
33
|
end
|
33
34
|
|
34
35
|
class TimeConverter
|
35
|
-
ISO_RE = /\A\d{4}-?\d{2}-?\d{2}([T ]?\d{2}(:?\d{2}(:?\d{2})?)?)?\Z/
|
36
|
+
ISO_RE = /\A\d{4}-?\d{2}-?\d{2}([T ]?\d{2}(:?\d{2}(:?\d{2}((\.)?\d{0,3}(Z)?)?)?)?)?\Z/
|
36
37
|
|
37
38
|
def call(value)
|
38
|
-
|
39
|
-
|
39
|
+
case value
|
40
|
+
when Time
|
41
|
+
value.getutc
|
42
|
+
when String
|
43
|
+
if value =~ ISO_RE
|
44
|
+
strip_timezone(Time.parse(value))
|
45
|
+
else
|
46
|
+
raise ConversionError.new("invalid time")
|
47
|
+
end
|
40
48
|
else
|
41
49
|
raise ConversionError.new("invalid time")
|
42
50
|
end
|
@@ -59,6 +67,8 @@ module InputSanitizer
|
|
59
67
|
'0' => false,
|
60
68
|
'yes' => true,
|
61
69
|
'no' => false,
|
70
|
+
1 => true,
|
71
|
+
0 => false,
|
62
72
|
}
|
63
73
|
|
64
74
|
def call(value)
|
@@ -22,7 +22,10 @@ class InputSanitizer::Sanitizer
|
|
22
22
|
self.class.fields.each do |field, hash|
|
23
23
|
type = hash[:type]
|
24
24
|
required = hash[:options][:required]
|
25
|
-
|
25
|
+
collection = hash[:options][:collection]
|
26
|
+
namespace = hash[:options][:namespace]
|
27
|
+
default = hash[:options][:default]
|
28
|
+
clean_field(field, type, required, collection, namespace, default)
|
26
29
|
end
|
27
30
|
@performed = true
|
28
31
|
@cleaned.freeze
|
@@ -73,6 +76,17 @@ class InputSanitizer::Sanitizer
|
|
73
76
|
self.set_keys_to_type(keys, converter)
|
74
77
|
end
|
75
78
|
|
79
|
+
def self.nested(*keys)
|
80
|
+
options = keys.pop
|
81
|
+
sanitizer = options.delete(:sanitizer)
|
82
|
+
keys.push(options)
|
83
|
+
raise "You did not define a sanitizer for nested value" if sanitizer == nil
|
84
|
+
converter = lambda { |value|
|
85
|
+
sanitizer.clean(value)
|
86
|
+
}
|
87
|
+
self.set_keys_to_type(keys, converter)
|
88
|
+
end
|
89
|
+
|
76
90
|
protected
|
77
91
|
def self.fields
|
78
92
|
@fields ||= {}
|
@@ -91,13 +105,15 @@ class InputSanitizer::Sanitizer
|
|
91
105
|
array.last.is_a?(Hash) ? array.last : {}
|
92
106
|
end
|
93
107
|
|
94
|
-
def clean_field(field, type, required)
|
108
|
+
def clean_field(field, type, required, collection, namespace, default)
|
95
109
|
if @data.has_key?(field)
|
96
110
|
begin
|
97
|
-
@cleaned[field] = convert(field, type)
|
111
|
+
@cleaned[field] = convert(field, type, collection, namespace)
|
98
112
|
rescue InputSanitizer::ConversionError => ex
|
99
113
|
add_error(field, :invalid_value, @data[field], ex.message)
|
100
114
|
end
|
115
|
+
elsif default
|
116
|
+
@cleaned[field] = converter(type).call(default)
|
101
117
|
elsif required
|
102
118
|
add_missing(field)
|
103
119
|
end
|
@@ -116,8 +132,22 @@ class InputSanitizer::Sanitizer
|
|
116
132
|
add_error(field, :missing, nil, nil)
|
117
133
|
end
|
118
134
|
|
119
|
-
def convert(field, type)
|
120
|
-
|
135
|
+
def convert(field, type, collection, namespace)
|
136
|
+
if collection
|
137
|
+
@data[field].map { |v|
|
138
|
+
convert_single(type, v, namespace)
|
139
|
+
}
|
140
|
+
else
|
141
|
+
convert_single(type, @data[field], namespace)
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def convert_single(type, value, namespace)
|
146
|
+
if namespace
|
147
|
+
{ namespace => converter(type).call(value[namespace]) }
|
148
|
+
else
|
149
|
+
converter(type).call(value)
|
150
|
+
end
|
121
151
|
end
|
122
152
|
|
123
153
|
def converter(type)
|
@@ -81,14 +81,27 @@ describe InputSanitizer::TimeConverter do
|
|
81
81
|
converter.call("2012-05-15 13:42:54").should == t
|
82
82
|
converter.call("2012-05-15T13:42:54").should == t
|
83
83
|
converter.call("20120515134254").should == t
|
84
|
+
end
|
85
|
+
|
86
|
+
it "works with miliseconds" do
|
87
|
+
t = Time.utc(2012, 5, 15, 13, 42, 54)
|
88
|
+
converter.call("2012-05-15 13:42:54.000").should == t
|
89
|
+
converter.call("2012-05-15T13:42:54.000").should == t
|
90
|
+
converter.call("20120515134254000").should == t
|
91
|
+
end
|
84
92
|
|
93
|
+
it "works with Z at the end" do
|
94
|
+
t = Time.utc(2012, 5, 15, 13, 42, 54)
|
95
|
+
converter.call("2012-05-15 13:42:54.000Z").should == t
|
96
|
+
converter.call("2012-05-15T13:42:54.000Z").should == t
|
97
|
+
converter.call("2012-05-15T13:42:54Z").should == t
|
98
|
+
converter.call("20120515134254000Z").should == t
|
85
99
|
end
|
86
100
|
|
87
101
|
it "does not require time part" do
|
88
102
|
converter.call("2012-05-15 13:42").should == Time.utc(2012, 5, 15, 13, 42)
|
89
103
|
converter.call("2012-05-15 13").should == Time.utc(2012, 5, 15, 13)
|
90
104
|
converter.call("2012-05-15").should == Time.utc(2012, 5, 15)
|
91
|
-
|
92
105
|
end
|
93
106
|
|
94
107
|
it "raises error if can format is wrong" do
|
@@ -98,4 +111,9 @@ describe InputSanitizer::TimeConverter do
|
|
98
111
|
it "raises error if date is wrong" do
|
99
112
|
lambda { converter.call("2012-02-32") }.should raise_error(InputSanitizer::ConversionError)
|
100
113
|
end
|
114
|
+
|
115
|
+
it "allows the instance of Time" do
|
116
|
+
t = Time.now
|
117
|
+
converter.call(t).should == t.utc
|
118
|
+
end
|
101
119
|
end
|
data/spec/sanitizer_spec.rb
CHANGED
@@ -1,11 +1,19 @@
|
|
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
|
9
17
|
end
|
10
18
|
|
11
19
|
class BrokenCustomSanitizer < InputSanitizer::Sanitizer
|
@@ -28,12 +36,17 @@ class RequiredCustom < BasicSanitizer
|
|
28
36
|
custom :c1, :required => true, :converter => lambda { |v| v }
|
29
37
|
end
|
30
38
|
|
39
|
+
class DefaultParameters < BasicSanitizer
|
40
|
+
integer :funky_number, :default => 5
|
41
|
+
custom :fixed_stuff, :converter => lambda {|v| v }, :default => "default string"
|
42
|
+
end
|
43
|
+
|
31
44
|
describe InputSanitizer::Sanitizer do
|
32
45
|
let(:sanitizer) { BasicSanitizer.new(@params) }
|
33
46
|
|
34
47
|
describe ".clean" do
|
35
48
|
it "returns cleaned data" do
|
36
|
-
clean_data =
|
49
|
+
clean_data = double
|
37
50
|
BasicSanitizer.any_instance.should_receive(:cleaned).and_return(clean_data)
|
38
51
|
BasicSanitizer.clean({}).should be(clean_data)
|
39
52
|
end
|
@@ -83,6 +96,30 @@ describe InputSanitizer::Sanitizer do
|
|
83
96
|
cleaned.should_not have_key(:d)
|
84
97
|
end
|
85
98
|
|
99
|
+
it "preserves namespace" do
|
100
|
+
value = { :value => 5 }
|
101
|
+
@params = { :namespaced => value }
|
102
|
+
|
103
|
+
cleaned[:namespaced].should eq(value)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "maps values for collection fields" do
|
107
|
+
numbers = [3, 5, 6]
|
108
|
+
@params = { :array => numbers }
|
109
|
+
|
110
|
+
cleaned[:array].should eq(numbers)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "maps values for collection fields with namespace" do
|
114
|
+
numbers = [
|
115
|
+
{ :value => 2 },
|
116
|
+
{ :value => 5 }
|
117
|
+
]
|
118
|
+
@params = { :namespaced_array => numbers }
|
119
|
+
|
120
|
+
cleaned[:namespaced_array].should eq(numbers)
|
121
|
+
end
|
122
|
+
|
86
123
|
it "silently discards cast errors" do
|
87
124
|
@params = {:num => "f"}
|
88
125
|
|
@@ -106,6 +143,32 @@ describe InputSanitizer::Sanitizer do
|
|
106
143
|
cleaned[:is_nice].should == 42
|
107
144
|
end
|
108
145
|
|
146
|
+
context "when sanitizer is initialized with default values" do
|
147
|
+
context "when paremeters are not overwriten" do
|
148
|
+
let(:sanitizer) { DefaultParameters.new({}) }
|
149
|
+
|
150
|
+
it "returns default value for non custom key" do
|
151
|
+
sanitizer.cleaned[:funky_number].should == 5
|
152
|
+
end
|
153
|
+
|
154
|
+
it "returns default value for custom key" do
|
155
|
+
sanitizer.cleaned[:fixed_stuff].should == "default string"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
context "when parameters are overwriten" do
|
160
|
+
let(:sanitizer) { DefaultParameters.new({ :funky_number => 2, :fixed_stuff => "fixed" }) }
|
161
|
+
|
162
|
+
it "returns default value for non custom key" do
|
163
|
+
sanitizer.cleaned[:funky_number].should == 2
|
164
|
+
end
|
165
|
+
|
166
|
+
it "returns default value for custom key" do
|
167
|
+
sanitizer.cleaned[:fixed_stuff].should == "fixed"
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
109
172
|
end
|
110
173
|
|
111
174
|
describe ".custom" do
|
@@ -126,6 +189,25 @@ describe InputSanitizer::Sanitizer do
|
|
126
189
|
end
|
127
190
|
end
|
128
191
|
|
192
|
+
describe ".nested" do
|
193
|
+
let(:sanitizer) { BasicSanitizer.new(@params) }
|
194
|
+
let(:cleaned) { sanitizer.cleaned }
|
195
|
+
|
196
|
+
it "sanitizes nested values" do
|
197
|
+
nested = [
|
198
|
+
{ :nested => { :foo => "5" } },
|
199
|
+
{ :nested => { :foo => 8 } },
|
200
|
+
]
|
201
|
+
@params = { :stuff => nested }
|
202
|
+
|
203
|
+
expected = [
|
204
|
+
{ :nested => { :foo => 5 } },
|
205
|
+
{ :nested => { :foo => 8 } },
|
206
|
+
]
|
207
|
+
cleaned[:stuff].should eq(expected)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
129
211
|
describe ".converters" do
|
130
212
|
let(:sanitizer) { InputSanitizer::Sanitizer }
|
131
213
|
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: input_sanitizer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.2.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Tomek Paczkowski
|
@@ -11,38 +10,34 @@ authors:
|
|
11
10
|
autorequire:
|
12
11
|
bindir: bin
|
13
12
|
cert_chain: []
|
14
|
-
date: 2013-
|
13
|
+
date: 2013-12-11 00:00:00.000000000 Z
|
15
14
|
dependencies:
|
16
15
|
- !ruby/object:Gem::Dependency
|
17
16
|
name: rspec
|
18
17
|
requirement: !ruby/object:Gem::Requirement
|
19
|
-
none: false
|
20
18
|
requirements:
|
21
|
-
- -
|
19
|
+
- - '>='
|
22
20
|
- !ruby/object:Gem::Version
|
23
21
|
version: '0'
|
24
22
|
type: :development
|
25
23
|
prerelease: false
|
26
24
|
version_requirements: !ruby/object:Gem::Requirement
|
27
|
-
none: false
|
28
25
|
requirements:
|
29
|
-
- -
|
26
|
+
- - '>='
|
30
27
|
- !ruby/object:Gem::Version
|
31
28
|
version: '0'
|
32
29
|
- !ruby/object:Gem::Dependency
|
33
30
|
name: simplecov
|
34
31
|
requirement: !ruby/object:Gem::Requirement
|
35
|
-
none: false
|
36
32
|
requirements:
|
37
|
-
- -
|
33
|
+
- - '>='
|
38
34
|
- !ruby/object:Gem::Version
|
39
35
|
version: '0'
|
40
36
|
type: :development
|
41
37
|
prerelease: false
|
42
38
|
version_requirements: !ruby/object:Gem::Requirement
|
43
|
-
none: false
|
44
39
|
requirements:
|
45
|
-
- -
|
40
|
+
- - '>='
|
46
41
|
- !ruby/object:Gem::Version
|
47
42
|
version: '0'
|
48
43
|
description: Gem to sanitize hash of incoming data
|
@@ -75,27 +70,26 @@ files:
|
|
75
70
|
- spec/spec_helper.rb
|
76
71
|
homepage: ''
|
77
72
|
licenses: []
|
73
|
+
metadata: {}
|
78
74
|
post_install_message:
|
79
75
|
rdoc_options: []
|
80
76
|
require_paths:
|
81
77
|
- lib
|
82
78
|
required_ruby_version: !ruby/object:Gem::Requirement
|
83
|
-
none: false
|
84
79
|
requirements:
|
85
|
-
- -
|
80
|
+
- - '>='
|
86
81
|
- !ruby/object:Gem::Version
|
87
82
|
version: '0'
|
88
83
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
-
none: false
|
90
84
|
requirements:
|
91
|
-
- -
|
85
|
+
- - '>='
|
92
86
|
- !ruby/object:Gem::Version
|
93
87
|
version: '0'
|
94
88
|
requirements: []
|
95
89
|
rubyforge_project:
|
96
|
-
rubygems_version:
|
90
|
+
rubygems_version: 2.0.14
|
97
91
|
signing_key:
|
98
|
-
specification_version:
|
92
|
+
specification_version: 4
|
99
93
|
summary: Gem to sanitize hash of incoming data
|
100
94
|
test_files:
|
101
95
|
- spec/default_converters_spec.rb
|