sinatra-params-validator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source :rubygems
2
+
3
+ gem 'rack', '1.5.2'
4
+ gem 'sinatra', '1.4.2'
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2013 tsov, lube8uy
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,116 @@
1
+ # sinatra-params-validator
2
+ ========================
3
+
4
+ ## Description
5
+
6
+ This sinatra module validates the incoming parameter and lets you configure the pattern.
7
+ Once it's registered with your sinatra app, it will act as a before filter, that validates your parameters.
8
+ You can configure it with the newly available sinatra method `validation_required`.
9
+
10
+ ## Sinatra Module
11
+
12
+ Configure your routes to require parameters and validate their values. If the
13
+ validator finds errors, it will execute sinatras halt method, which will prevent
14
+ invocation of your sinatra code block, and set the response status to 400. The missing
15
+ or invalid parameters can be found in the environment variable, like in the example
16
+ below. That means you can customize your own error responses, for example by catching the errors
17
+ with some middleware.
18
+
19
+ ### Examples
20
+
21
+ ```ruby
22
+ require 'sinatra'
23
+
24
+ class App < Sinatra::Base
25
+ register Rack::Validator::Sinatra
26
+
27
+ helpers do
28
+ def missing_parameters
29
+ @env['validator.missing']
30
+ end
31
+
32
+ def invalid_parameters
33
+ @env['validator.invalid']
34
+ end
35
+
36
+ def messages
37
+ @env['validator.messages']
38
+ end
39
+ end
40
+
41
+ after do
42
+ puts missing_parameters
43
+ puts invalid_parameters
44
+ puts messages
45
+ puts params
46
+ end
47
+
48
+ validation_required :GET, '/', :params => [
49
+ { :name => :name, :required => true },
50
+ { :name => :email, :type => :email, :required => true },
51
+ { :name => :age, :range => [ 0, 120 ], :default => 1000 },
52
+ { :name => :latitude, :type => :float, :default => 0.0 },
53
+ { :name => :longitude, :type => :float, :default => 0.0 },
54
+ { :name => :message },
55
+ { :name => :price, :matches => /^[\d]*.[\d]{2}$/ }
56
+ ]
57
+
58
+ get '/' do
59
+
60
+ end
61
+
62
+ validation_required :POST, '/group', :params => [
63
+ { :name => :name, :required => true }
64
+ ]
65
+
66
+ post '/group' do
67
+
68
+ end
69
+
70
+ end
71
+ ```
72
+
73
+ Try it out yourself and run this in the root directory `rackup example/app.rb`.
74
+
75
+ ## Validator class
76
+
77
+ A class with several methods to validate and clean data from sinatra params holder.
78
+ Can be used for an adopter for other libraries/frameworks, like rails.
79
+
80
+ ### Examples
81
+
82
+ Initialize class in lazy mode, this means that once a validation fail the following ones are not executed:
83
+
84
+ ```ruby
85
+ validator = Rack::Validator.new(params)
86
+ #required_3 is not present
87
+ validator.required [:required_1, :required_2, :required_3]
88
+ validator.trim
89
+ validator.downcase [:required_2, :other_param]
90
+ validator.is_in_range 3, 32, :required_1
91
+ validator.is_email :contact
92
+ validator.matches /[a-z]{2}_[A-Z]{2}|[a-z]{2}/i, :locale
93
+
94
+ if validator.has_errors?
95
+ p validator.messages.join('|')
96
+ #Inputs "required_3 is required"
97
+ end
98
+ ```
99
+
100
+ If you want to get all the errors at the end of the validation calls pass false as second parameter in the constructor:
101
+ validator = Rack::Validator.new(params, true)
102
+
103
+ Available methods:
104
+
105
+ * trim
106
+ * downcase
107
+ * required
108
+ * is_integer
109
+ * is_float
110
+ * is_greater_equal_than
111
+ * is_in_range
112
+ * is_less_equal_than
113
+ * is_email
114
+ * matches
115
+
116
+ To see more examples check tests/params_validator_spec.rb
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,234 @@
1
+ require 'rack'
2
+
3
+ module Rack
4
+ class Validator
5
+
6
+ attr_reader :invalid_params
7
+ attr_reader :missing_params
8
+ attr_reader :messages
9
+ attr_accessor :lazy_mode
10
+
11
+ def initialize(params, lazy_mode = true)
12
+ @params = params
13
+ @invalid_params = []
14
+ @missing_params = []
15
+ @messages = []
16
+ @lazy_mode = lazy_mode
17
+ end
18
+
19
+ def has_errors?
20
+ @invalid_params.length > 0 or @missing_params.length > 0
21
+ end
22
+
23
+ def trim
24
+ @params.each_key { |k| @params[k] = @params[k].strip if @params[k]}
25
+ end
26
+
27
+ def downcase(keys)
28
+ keys.each { |k| @params[k.to_s] = @params[k.to_s].to_s.downcase if @params[k.to_s]}
29
+ end
30
+
31
+ def required(keys)
32
+ if lazy_check_disabled
33
+ keys.each { |k|
34
+ k = k.to_s
35
+ unless @params.has_key?(k)
36
+ @invalid_params.push(k)
37
+ @missing_params.push(k)
38
+ @messages.push("#{k} is required")
39
+ end
40
+ }
41
+ end
42
+ end
43
+
44
+ def is_integer(key)
45
+ if lazy_check_disabled
46
+ key = key.to_s
47
+ value = @params[key]
48
+ unless is_valid_integer(value)
49
+ @invalid_params.push(key)
50
+ @messages.push("#{key} is not an integer")
51
+ end
52
+ end
53
+ end
54
+
55
+ def is_float(key)
56
+ if lazy_check_disabled
57
+ key = key.to_s
58
+ value = @params[key]
59
+ unless is_valid_float(value)
60
+ @invalid_params.push(key)
61
+ @messages.push("#{key} is not a float")
62
+ end
63
+ end
64
+ end
65
+
66
+ def is_greater_equal_than(min, key)
67
+ if lazy_check_disabled
68
+ key = key.to_s
69
+ if !is_valid_float(@params[key])
70
+ if !@params[key] || @params[key].length < min
71
+ @invalid_params.push(key)
72
+ @messages.push("#{key} length is less than #{min}")
73
+ end
74
+ else
75
+ value = is_valid_integer(@params[key]) ? @params[key].to_i : @params[key].to_f
76
+ if !value || value < min
77
+ @invalid_params.push(key)
78
+ @messages.push("#{key} is less than #{min}")
79
+ end
80
+ end
81
+ end
82
+ end
83
+
84
+ def is_in_range(min, max, key)
85
+ if lazy_check_disabled
86
+ key = key.to_s
87
+ unless is_valid_float(@params[key])
88
+ if !@params[key] || @params[key].length < min || @params[key].length > max
89
+ @invalid_params.push(key)
90
+ @messages.push("#{key} length is not in range #{min},#{max}")
91
+ end
92
+ else
93
+ value = is_valid_integer(@params[key]) ? @params[key].to_i : @params[key].to_f
94
+ if !value || value < min || value > max
95
+ @invalid_params.push(key)
96
+ @messages.push("#{key} is not in range #{min},#{max}")
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ def is_less_equal_than(max, key)
103
+ if lazy_check_disabled
104
+ key = key.to_s
105
+ unless is_valid_float(@params[key])
106
+ if !@params[key] || @params[key].length > max
107
+ @invalid_params.push(key)
108
+ @messages.push("#{key} length is greater than #{max}")
109
+ end
110
+ else
111
+ value = is_valid_integer(@params[key]) ? @params[key].to_i : @params[key].to_f
112
+ if !value || value > max
113
+ @invalid_params.push(key)
114
+ @messages.push("#{key} is greater than #{max}")
115
+ end
116
+ end
117
+ end
118
+ end
119
+
120
+ def is_email(key)
121
+ if lazy_check_disabled
122
+ key = key.to_s
123
+ unless @params[key].to_s[/^\S+@\S+\.\S+$/]
124
+ @invalid_params.push(key)
125
+ @messages.push("#{key} is not a valid email")
126
+ end
127
+ end
128
+ end
129
+
130
+ def matches(regexp, key)
131
+ if lazy_check_disabled
132
+ key = key.to_s
133
+ unless @params[key] =~ regexp
134
+ @invalid_params.push(key)
135
+ @messages.push("#{key} is not a valid expression")
136
+ end
137
+ end
138
+ end
139
+
140
+ private
141
+
142
+ def lazy_check_disabled
143
+ return !@lazy_mode || !has_errors?
144
+ end
145
+
146
+ def is_valid_integer(value)
147
+ key = key.to_s
148
+ value.to_i.to_s == value.to_s
149
+ end
150
+
151
+ def is_valid_float(value)
152
+ key = key.to_s
153
+ value.to_f.to_s == value.to_s || is_valid_integer(value)
154
+ end
155
+
156
+ module Sinatra
157
+
158
+ def validation_required(method, path, options = { })
159
+ before path do
160
+ validate_parameters(options) if same_method? method
161
+ end
162
+ end
163
+
164
+ module Helpers
165
+ def same_method?(method)
166
+ @env['REQUEST_METHOD'] == method.to_s
167
+ end
168
+
169
+ # TODO: Needs a general cleanup!!!
170
+ def validate_parameters(options)
171
+ validator = Rack::Validator.new params, false
172
+ required_params = [ ]
173
+ integer_params = [ ]
174
+ float_params = [ ]
175
+ email_params = [ ]
176
+ range_params = [ ]
177
+ matches_params = [ ]
178
+ default_params = [ ]
179
+
180
+ options[:params].each do |param|
181
+ required_params << (param[:name]) if param[:required]
182
+ integer_params << (param) if param[:type] == :integer
183
+ float_params << (param) if param[:type] == :float
184
+ email_params << (param) if param[:type] == :email
185
+ range_params << (param) if param[:range]
186
+ matches_params << (param) if param[:matches]
187
+ default_params << (param) if param[:default]
188
+ end
189
+
190
+ validator.required required_params
191
+ integer_params.each do |param|
192
+ validator.is_integer param[:name] unless params[param[:name].to_s].nil?
193
+ end
194
+ float_params.each do |param|
195
+ validator.is_float param[:name] unless params[param[:name].to_s].nil?
196
+ end
197
+ email_params.each do |param|
198
+ validator.is_email param[:name] unless params[param[:name].to_s].nil?
199
+ end
200
+ range_params.each do |param|
201
+ validator.is_in_range param[:range].first, param[:range].last, param[:name] unless params[param[:name].to_s].nil?
202
+ end
203
+ matches_params.each do |param|
204
+ validator.matches param[:matches], param[:name] unless params[param[:name].to_s].nil?
205
+ end
206
+
207
+ default_params.each do |param|
208
+ if params[param[:name].to_s].nil?
209
+ params[param[:name].to_s] = param[:default]
210
+ validator.invalid_params.delete param[:name]
211
+ validator.missing_params.delete param[:name]
212
+ end
213
+ end
214
+
215
+ if validator.has_errors?
216
+ @env['validator.missing'] = validator.missing_params
217
+ @env['validator.invalid'] = validator.invalid_params
218
+ @env['validator.messages'] = validator.messages
219
+ halt missing_params!
220
+ end
221
+ end
222
+
223
+ def missing_params!
224
+ @response.status = 400
225
+ end
226
+ end
227
+
228
+ def self.registered(base)
229
+ base.helpers Helpers
230
+ end
231
+
232
+ end
233
+ end
234
+ end
@@ -0,0 +1,14 @@
1
+ $: << File.dirname(__FILE__) + "/lib"
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = "sinatra-params-validator"
5
+ spec.version = IO.read("VERSION")
6
+ spec.authors = ["tsov", "lube8buy"]
7
+ spec.email = "tsov@me.com"
8
+ spec.homepage = "http://github.com/tsov/#{spec.name}"
9
+ spec.summary = "A Sinatra Module to validate incoming parameters"
10
+ spec.description = "This sinatra module validates the incoming parameter and lets you configure the pattern."
11
+
12
+ spec.files = Dir["lib/**/*", "VERSION", "LICENSE", "README.md", "Gemfile", "*.gemspec"]
13
+ spec.license = "MIT"
14
+ end
metadata ADDED
@@ -0,0 +1,54 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sinatra-params-validator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - tsov
9
+ - lube8buy
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-05-30 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description: This sinatra module validates the incoming parameter and lets you configure
16
+ the pattern.
17
+ email: tsov@me.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/rack/validator/sinatra.rb
23
+ - VERSION
24
+ - LICENSE
25
+ - README.md
26
+ - Gemfile
27
+ - sinatra-params-validator.gemspec
28
+ homepage: http://github.com/tsov/sinatra-params-validator
29
+ licenses:
30
+ - MIT
31
+ post_install_message:
32
+ rdoc_options: []
33
+ require_paths:
34
+ - lib
35
+ required_ruby_version: !ruby/object:Gem::Requirement
36
+ none: false
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ requirements: []
48
+ rubyforge_project:
49
+ rubygems_version: 1.8.24
50
+ signing_key:
51
+ specification_version: 3
52
+ summary: A Sinatra Module to validate incoming parameters
53
+ test_files: []
54
+ has_rdoc: