strelka 0.0.1.pre177 → 0.0.1.pre184

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. data/ChangeLog +111 -16
  2. data/Manifest.txt +8 -8
  3. data/Rakefile +3 -3
  4. data/bin/leash +51 -28
  5. data/examples/{auth-demo.rb → apps/auth-demo} +3 -3
  6. data/examples/{auth-demo2.rb → apps/auth-demo2} +0 -0
  7. data/examples/{sessions-demo.rb → apps/sessions-demo} +0 -0
  8. data/examples/config.yml +5 -1
  9. data/examples/{examples.css → static/examples.css} +0 -0
  10. data/examples/{examples.html → static/examples.html} +0 -0
  11. data/examples/{auth-form.tmpl → templates/auth-form.tmpl} +0 -0
  12. data/examples/{auth-success.tmpl → templates/auth-success.tmpl} +0 -0
  13. data/examples/{layout.tmpl → templates/layout.tmpl} +0 -0
  14. data/lib/strelka/app/auth.rb +18 -8
  15. data/lib/strelka/app/errors.rb +3 -2
  16. data/lib/strelka/app/filters.rb +2 -0
  17. data/lib/strelka/app/negotiation.rb +2 -0
  18. data/lib/strelka/app/parameters.rb +18 -140
  19. data/lib/strelka/app/plugins.rb +84 -26
  20. data/lib/strelka/app/restresources.rb +26 -18
  21. data/lib/strelka/app/routing.rb +8 -2
  22. data/lib/strelka/app/sessions.rb +7 -0
  23. data/lib/strelka/app/templating.rb +1 -1
  24. data/lib/strelka/app.rb +25 -1
  25. data/lib/strelka/constants.rb +3 -1
  26. data/lib/strelka/paramvalidator.rb +251 -74
  27. data/lib/strelka/session/default.rb +1 -1
  28. data/spec/strelka/app/auth_spec.rb +37 -0
  29. data/spec/strelka/app/errors_spec.rb +0 -2
  30. data/spec/strelka/app/filters_spec.rb +1 -1
  31. data/spec/strelka/app/parameters_spec.rb +4 -92
  32. data/spec/strelka/app/plugins_spec.rb +64 -2
  33. data/spec/strelka/app/restresources_spec.rb +3 -0
  34. data/spec/strelka/app/routing_spec.rb +5 -5
  35. data/spec/strelka/paramvalidator_spec.rb +294 -385
  36. data.tar.gz.sig +0 -0
  37. metadata +126 -46
  38. metadata.gz.sig +0 -0
@@ -20,49 +20,43 @@ require 'strelka/app' unless defined?( Strelka::App )
20
20
  #
21
21
  # require 'strelka/app/formvalidator'
22
22
  #
23
- # # Profile specifies validation criteria for input
24
- # profile = {
25
- # :required => :name,
26
- # :optional => [:email, :description],
27
- # :filters => [:strip, :squeeze],
28
- # :untaint_all_constraints => true,
29
- # :descriptions => {
30
- # :email => "Customer Email",
31
- # :description => "Issue Description",
32
- # :name => "Customer Name",
33
- # },
34
- # :constraints => {
35
- # :email => :email,
36
- # :name => /^[\x20-\x7f]+$/,
37
- # :description => /^[\x20-\x7f]+$/,
38
- # },
39
- # }
40
- #
41
- # # Create a validator object and pass in a hash of request parameters and the
42
- # # profile hash.
43
23
  # validator = Strelka::ParamValidator.new
44
- # validator.validate( req_params, profile )
45
24
  #
46
- # # Now if there weren't any errors, send the success page
25
+ # # Add validation criteria for input parameters
26
+ # validator.add( :name, /^(?<lastname>\S+), (?<firstname>\S+)$/, "Customer Name" )
27
+ # validator.add( :email, "Customer Email" )
28
+ # validator.add( :feedback, :printable, "Customer Feedback" )
29
+ #
30
+ # # Untaint all parameter values which match their constraints
31
+ # validate.untaint_all_constraints = true
32
+ #
33
+ # # Now pass in tainted values in a hash (e.g., from an HTML form)
34
+ # validator.validate( req.params )
35
+ #
36
+ # # Now if there weren't any errors, use some form values to fill out the
37
+ # # success page template
47
38
  # if validator.okay?
48
- # return success_template
39
+ # tmpl = template :success
40
+ # tmpl.firstname = validator[:name][:firstname]
41
+ # tmpl.lastname = validator[:name][:lastname]
42
+ # tmpl.email = validator[:email]
43
+ # tmpl.feedback = validator[:feedback]
44
+ # return tmpl
49
45
  #
50
46
  # # Otherwise fill in the error template with auto-generated error messages
51
47
  # # and return that instead.
52
48
  # else
53
- # failure_template.errors( validator.error_messages )
54
- # return failure_template
49
+ # tmpl = template :feedback_form
50
+ # tmpl.errors = validator.error_messages
51
+ # return tmpl
55
52
  # end
56
53
  #
57
54
  class Strelka::ParamValidator < ::FormValidator
58
55
  extend Forwardable
59
56
  include Strelka::Loggable
60
57
 
61
-
62
- # Validation default config
63
- DEFAULT_PROFILE = {
64
- :descriptions => {},
65
- }
58
+ # Options that are passed as Symbols to .param
59
+ FLAGS = [ :required, :untaint ]
66
60
 
67
61
  #
68
62
  # RFC822 Email Address Regex
@@ -110,6 +104,7 @@ class Strelka::ParamValidator < ::FormValidator
110
104
 
111
105
  # The Hash of builtin constraints that are validated against a regular
112
106
  # expression.
107
+ # :TODO: Document that these are the built-in constraints that can be used in a route
113
108
  BUILTIN_CONSTRAINT_PATTERNS = {
114
109
  :boolean => /^(?<boolean>t(?:rue)?|y(?:es)?|[10]|no?|f(?:alse)?)$/i,
115
110
  :integer => /^(?<integer>[\-\+]?\d+)$/,
@@ -124,6 +119,11 @@ class Strelka::ParamValidator < ::FormValidator
124
119
  :uri => /^(?<uri>#{URI::URI_REF})$/,
125
120
  }
126
121
 
122
+ # Pattern to use to strip binding operators from parameter patterns so they
123
+ # can be used in the middle of routing Regexps.
124
+ PARAMETER_PATTERN_STRIP_RE = Regexp.union( '^', '$', '\\A', '\\z', '\\Z' )
125
+
126
+
127
127
 
128
128
  ### Return a Regex for the built-in constraint associated with the given +name+. If
129
129
  ### the builtin constraint is not pattern-based, or there is no such constraint,
@@ -138,11 +138,19 @@ class Strelka::ParamValidator < ::FormValidator
138
138
  #################################################################
139
139
 
140
140
  ### Create a new Strelka::ParamValidator object.
141
- def initialize( profile, params=nil )
141
+ def initialize( profile={} )
142
+ @profile = {
143
+ descriptions: {},
144
+ required: [],
145
+ optional: [],
146
+ descriptions: {},
147
+ constraints: {},
148
+ untaint_constraint_fields: [],
149
+ }.merge( profile )
150
+
142
151
  @form = {}
143
152
  @raw_form = {}
144
- @profile = DEFAULT_PROFILE.merge( profile )
145
- @invalid_fields = []
153
+ @invalid_fields = {}
146
154
  @missing_fields = []
147
155
  @unknown_fields = []
148
156
  @required_fields = []
@@ -150,18 +158,22 @@ class Strelka::ParamValidator < ::FormValidator
150
158
  @optional_fields = []
151
159
  @filters_array = []
152
160
  @untaint_fields = []
161
+ @untaint_all = false
153
162
 
154
163
  @parsed_params = nil
155
-
156
- self.validate( params ) if params
157
164
  end
158
165
 
159
166
 
160
167
  ### Copy constructor.
161
168
  def initialize_copy( original )
169
+ super
170
+
171
+ @profile = original.profile.dup
172
+ @profile.each_key {|k| @profile[k] = @profile[k].clone }
173
+ self.log.debug "Copied validator profile: %p" % [ @profile ]
174
+
162
175
  @form = @form.clone
163
176
  @raw_form = @form.clone
164
- @profile = @profile.clone
165
177
  @invalid_fields = @invalid_fields.clone
166
178
  @missing_fields = @missing_fields.clone
167
179
  @unknown_fields = @unknown_fields.clone
@@ -170,6 +182,7 @@ class Strelka::ParamValidator < ::FormValidator
170
182
  @optional_fields = @optional_fields.clone
171
183
  @filters_array = @filters_array.clone
172
184
  @untaint_fields = @untaint_fields.clone
185
+ @untaint_all = original.untaint_all?
173
186
 
174
187
  @parsed_params = @parsed_params.clone if @parsed_params
175
188
  end
@@ -180,12 +193,103 @@ class Strelka::ParamValidator < ::FormValidator
180
193
  public
181
194
  ######
182
195
 
196
+ # The profile hash
197
+ attr_reader :profile
198
+
183
199
  # The raw form data Hash
184
200
  attr_reader :raw_form
185
201
 
186
202
  # The validated form data Hash
187
203
  attr_reader :form
188
204
 
205
+ # Global untainting flag
206
+ attr_accessor :untaint_all
207
+ alias_method :untaint_all_constraints=, :untaint_all=
208
+ alias_method :untaint_all?, :untaint_all
209
+ alias_method :untaint_all_constraints, :untaint_all
210
+ alias_method :untaint_all_constraints?, :untaint_all
211
+
212
+
213
+
214
+ ### Return the Array of declared parameter validations.
215
+ def param_names
216
+ return self.profile[:required] | self.profile[:optional]
217
+ end
218
+
219
+
220
+ ### Fetch the constraint/s that apply to the parameter with the given
221
+ ### +name+.
222
+ def constraint_for( name )
223
+ constraint = self.profile[:constraints][ name.to_sym ] or
224
+ raise ScriptError, "no parameter %p defined" % [ name ]
225
+ return constraint
226
+ end
227
+
228
+
229
+ ### Fetch the constraint/s that apply to the parameter named +name+ as a
230
+ ### Regexp, if possible.
231
+ def constraint_regexp_for( name )
232
+ self.log.debug " searching for a constraint for %p" % [ name ]
233
+
234
+ # Munge the constraint into a Regexp
235
+ constraint = self.constraint_for( name )
236
+ re = case constraint
237
+ when Regexp
238
+ self.log.debug " regex constraint is: %p" % [ constraint ]
239
+ constraint
240
+ when Array
241
+ sub_res = constraint.map( &self.method(:extract_route_from_constraint) )
242
+ Regexp.union( sub_res )
243
+ when Symbol
244
+ self.class.pattern_for_constraint( constraint ) or
245
+ raise ScriptError, "no pattern for built-in %p constraint" % [ constraint ]
246
+ else
247
+ raise ScriptError,
248
+ "can't route on a parameter with a %p constraint %p" % [ constraint.class ]
249
+ end
250
+
251
+ self.log.debug " bounded constraint is: %p" % [ re ]
252
+
253
+ # Unbind the pattern from beginning or end of line.
254
+ # :TODO: This is pretty ugly. Find a better way of modifying the regex.
255
+ re_str = re.to_s.
256
+ sub( %r{\(\?[\-mix]+:(.*)\)}, '\\1' ).
257
+ gsub( PARAMETER_PATTERN_STRIP_RE, '' )
258
+ self.log.debug " stripped constraint pattern down to: %p" % [ re_str ]
259
+
260
+ return Regexp.new( "(?<#{name}>#{re_str})", re.options )
261
+ end
262
+
263
+
264
+ ### :call-seq:
265
+ ### param( name, *flags )
266
+ ### param( name, constraint, *flags )
267
+ ### param( name, description, *flags )
268
+ ### param( name, constraint, description, *flags )
269
+ ###
270
+ ### Add a validation for a parameter with the specified +name+. The +args+ can include
271
+ ### a constraint, a description, and one or more flags.
272
+ def add( name, *args, &block )
273
+ name = name.to_sym
274
+ raise ArgumentError,
275
+ "parameter %p is already defined; perhaps you meant to use #override?" % [name] if
276
+ self.param_names.include?( name )
277
+
278
+ self.set_param( name, *args, &block )
279
+ end
280
+
281
+
282
+ ### Replace the existing parameter with the specified +name+. The +args+ replace
283
+ ### the existing description, constraints, and flags. See #add for details.
284
+ def override( name, *args, &block )
285
+ name = name.to_sym
286
+ raise ArgumentError,
287
+ "no parameter %p defined; perhaps you meant to use #add?" % [name] unless
288
+ self.param_names.include?( name )
289
+
290
+ self.set_param( name, *args, &block )
291
+ end
292
+
189
293
 
190
294
  ### Stringified description of the validator
191
295
  def to_s
@@ -198,6 +302,26 @@ class Strelka::ParamValidator < ::FormValidator
198
302
  end
199
303
 
200
304
 
305
+ ### Return a human-readable representation of the validator, suitable for debugging.
306
+ def inspect
307
+ required = self.profile[:required].collect do |field|
308
+ "%s (%p)" % [ field, self.profile[:constraints][field] ]
309
+ end.join( ',' )
310
+ optional = self.profile[:optional].collect do |field|
311
+ "%s (%p)" % [ field, self.profile[:constraints][field] ]
312
+ end.join( ',' )
313
+
314
+ return "#<%p:0x%016x %s, profile: [required: %s, optional: %s] global untaint: %s>" % [
315
+ self.class,
316
+ self.object_id / 2,
317
+ self.to_s,
318
+ required.empty? ? "(none)" : required,
319
+ optional.empty? ? "(none)" : optional,
320
+ self.untaint_all? ? "enabled" : "disabled",
321
+ ]
322
+ end
323
+
324
+
201
325
  ### Hash of field descriptions
202
326
  def descriptions
203
327
  return @profile[:descriptions]
@@ -212,19 +336,70 @@ class Strelka::ParamValidator < ::FormValidator
212
336
 
213
337
  ### Validate the input in +params+. If the optional +additional_profile+ is
214
338
  ### given, merge it with the validator's default profile before validating.
215
- def validate( params, additional_profile=nil )
339
+ def validate( params=nil, additional_profile=nil )
340
+ params ||= {}
341
+
342
+ self.log.info "Validating request params: %p with profile: %p" %
343
+ [ params, @profile ]
216
344
  @raw_form = params.dup
217
345
  profile = @profile
218
346
 
219
347
  if additional_profile
220
- self.log.debug "Merging additional profile %p" % [additional_profile]
348
+ self.log.debug " merging additional profile %p" % [ additional_profile ]
221
349
  profile = @profile.merge( additional_profile )
222
350
  end
223
351
 
352
+ self.log.debug "Calling superclass's validate: %p" % [ self ]
224
353
  super( params, profile )
225
354
  end
226
355
 
227
356
 
357
+ protected :convert_profile
358
+
359
+ # Load profile with a hash describing valid input.
360
+ def setup(form_data, profile)
361
+ @form = form_data
362
+ @profile = self.convert_profile( @profile )
363
+ end
364
+
365
+
366
+ ### Set the parameter +name+ in the profile to validate using the given +args+,
367
+ ### which are the same as the ones passed to #add and #override.
368
+ def set_param( name, *args, &block )
369
+ args.unshift( block ) if block
370
+
371
+ # Custom validator -- either a callback or a regex
372
+ if args.first.is_a?( Regexp ) || args.first.respond_to?( :call )
373
+ self.profile[:constraints][ name ] = args.shift
374
+
375
+ # Builtin match validator, either explicit or implied by the name
376
+ else
377
+ constraint = args.shift if args.first.is_a?( Symbol ) && !FLAGS.include?( args.first )
378
+ constraint ||= name
379
+
380
+ raise ArgumentError, "no builtin %p validator" % [ constraint ] unless
381
+ self.respond_to?( "match_#{constraint}" )
382
+ self.profile[:constraints][ name ] = constraint
383
+ end
384
+
385
+ self.profile[:descriptions][ name ] = args.shift if args.first.is_a?( String )
386
+
387
+ if args.include?( :required )
388
+ self.profile[:required] |= [ name ]
389
+ self.profile[:optional].delete( name )
390
+ else
391
+ self.profile[:required].delete( name )
392
+ self.profile[:optional] |= [ name ]
393
+ end
394
+
395
+ if args.include?( :untaint )
396
+ self.profile[:untaint_constraint_fields] |= [ name ]
397
+ else
398
+ self.profile[:untaint_constraint_fields].delete( :name )
399
+ end
400
+ end
401
+
402
+
228
403
  ### Overridden to remove the check for extra keys.
229
404
  def check_profile_syntax( profile )
230
405
  end
@@ -273,28 +448,21 @@ class Strelka::ParamValidator < ::FormValidator
273
448
  ### Returns +true+ if the given +field+ is one that should be untainted.
274
449
  def untaint?( field )
275
450
  self.log.debug "Checking to see if %p should be untainted." % [field]
276
- rval = ( @untaint_all ||
451
+ rval = ( self.untaint_all? ||
277
452
  @untaint_fields.include?(field) ||
278
453
  @untaint_fields.include?(field.to_sym) )
279
454
 
280
455
  if rval
281
456
  self.log.debug " ...yep it should."
282
457
  else
283
- self.log.debug " ...nope; untaint fields is: %p" % [ @untaint_fields ]
458
+ self.log.debug " ...nope; untaint_all is: %p, untaint fields is: %p" %
459
+ [ @untaint_all, @untaint_fields ]
284
460
  end
285
461
 
286
462
  return rval
287
463
  end
288
464
 
289
465
 
290
- ### Overridden so that the presence of :untaint_constraint_fields doesn't
291
- ### disable the :untaint_all_constraints flag.
292
- def untaint_all_constraints
293
- @untaint_all = @profile[:untaint_all_constraints] ? true : false
294
- end
295
-
296
-
297
-
298
466
  ### Return an array of field names which had some kind of error associated
299
467
  ### with them.
300
468
  def error_fields
@@ -412,8 +580,12 @@ class Strelka::ParamValidator < ::FormValidator
412
580
  end
413
581
 
414
582
 
583
+ #########
584
+ protected
585
+ #########
586
+
415
587
  #
416
- # :section: Constraint methods
588
+ # :section: Builtin Match Constraints
417
589
  #
418
590
 
419
591
  ### Try to match the specified +val+ using the built-in constraint pattern
@@ -521,9 +693,14 @@ class Strelka::ParamValidator < ::FormValidator
521
693
  end
522
694
 
523
695
 
696
+ #
697
+ # :section: Constraint method
698
+ #
699
+
524
700
  ### Apply one or more +constraints+ to the field value/s corresponding to
525
701
  ### +key+.
526
702
  def do_constraint( key, constraints )
703
+ self.log.debug "Applying constraints %p to field %p" % [ constraints, key ]
527
704
  constraints.each do |constraint|
528
705
  case constraint
529
706
  when String
@@ -640,7 +817,7 @@ class Strelka::ParamValidator < ::FormValidator
640
817
 
641
818
  ### Set the form value for the given +key+. If +value+ is false, add it to
642
819
  ### the list of invalid fields with a description derived from the specified
643
- ### +constraint+.
820
+ ### +constraint+. Called by constraint methods when they succeed.
644
821
  def set_form_value( key, value, constraint )
645
822
  key.untaint
646
823
 
@@ -680,30 +857,30 @@ class Strelka::ParamValidator < ::FormValidator
680
857
  ### The formvalidator filters method has a bug where he assumes an array
681
858
  ### when it is in fact a string for multiple values (ie anytime you have a
682
859
  ### text-area with newlines in it).
683
- def filters
684
- @filters_array = Array(@profile[:filters]) unless(@filters_array)
685
- @filters_array.each do |filter|
686
-
687
- if respond_to?( "filter_#{filter}" )
688
- @form.keys.each do |field|
689
- # If a key has multiple elements, apply filter to each element
690
- @field_array = Array( @form[field] )
691
-
692
- if @field_array.length > 1
693
- @field_array.each_index do |i|
694
- elem = @field_array[i]
695
- @field_array[i] = self.send("filter_#{filter}", elem)
696
- end
697
- else
698
- if not @form[field].to_s.empty?
699
- @form[field] = self.send("filter_#{filter}", @form[field].to_s)
700
- end
701
- end
702
- end
703
- end
704
- end
705
- @form
706
- end
860
+ # def filters
861
+ # @filters_array = Array(@profile[:filters]) unless(@filters_array)
862
+ # @filters_array.each do |filter|
863
+ #
864
+ # if respond_to?( "filter_#{filter}" )
865
+ # @form.keys.each do |field|
866
+ # # If a key has multiple elements, apply filter to each element
867
+ # @field_array = Array( @form[field] )
868
+ #
869
+ # if @field_array.length > 1
870
+ # @field_array.each_index do |i|
871
+ # elem = @field_array[i]
872
+ # @field_array[i] = self.send("filter_#{filter}", elem)
873
+ # end
874
+ # else
875
+ # if not @form[field].to_s.empty?
876
+ # @form[field] = self.send("filter_#{filter}", @form[field].to_s)
877
+ # end
878
+ # end
879
+ # end
880
+ # end
881
+ # end
882
+ # @form
883
+ # end
707
884
 
708
885
 
709
886
  #######
@@ -76,7 +76,7 @@ class Strelka::Session::Default < Strelka::Session
76
76
  id = $1.untaint if cookie.value =~ /^([[:xdigit:]]+)$/i
77
77
  end
78
78
 
79
- return id || SecureRandom.random_bytes.unpack( 'H*' ).join
79
+ return id || SecureRandom.hex
80
80
  end
81
81
 
82
82
 
@@ -52,6 +52,7 @@ describe Strelka::App::Auth do
52
52
  app = Class.new( Strelka::App ) do
53
53
  plugins :auth
54
54
  end
55
+ app.install_plugins
55
56
 
56
57
  @request_factory.get( '/api/v1/verify' ).should respond_to( :authenticated? )
57
58
  end
@@ -83,6 +84,10 @@ describe Strelka::App::Auth do
83
84
  end
84
85
  end
85
86
 
87
+ after( :each ) do
88
+ @app = nil
89
+ end
90
+
86
91
 
87
92
  it "applies auth to every request by default" do
88
93
  app = @app.new
@@ -111,6 +116,38 @@ describe Strelka::App::Auth do
111
116
  req.authenticated_user.should == 'anonymous'
112
117
  end
113
118
 
119
+ context "that has negative auth criteria for the root" do
120
+
121
+ before( :each ) do
122
+ @app.no_auth_for( '/' )
123
+ end
124
+
125
+ it "knows that it has auth criteria" do
126
+ @app.should have_auth_criteria()
127
+ end
128
+
129
+ it "doesn't pass a request for the root path through auth" do
130
+ req = @request_factory.get( '/api/v1/' )
131
+
132
+ app = @app.new
133
+ app.auth_provider.should_not_receive( :authenticate )
134
+ app.auth_provider.should_not_receive( :authorize )
135
+
136
+ app.handle( req )
137
+ end
138
+
139
+ it "passes a request for a path other than the root through auth" do
140
+ req = @request_factory.get( '/api/v1/console' )
141
+
142
+ app = @app.new
143
+ app.auth_provider.should_receive( :authenticate ).and_return( 'anonymous' )
144
+ app.auth_provider.should_receive( :authorize ).and_return( true )
145
+
146
+ app.handle( req )
147
+ end
148
+
149
+ end
150
+
114
151
  context "that has negative auth criteria" do
115
152
 
116
153
  before( :each ) do
@@ -42,14 +42,12 @@ describe Strelka::App::Errors do
42
42
  describe "an including App" do
43
43
 
44
44
  before( :each ) do
45
- Strelka.log.debug "Creating a new Strelka::App"
46
45
  @app = Class.new( Strelka::App ) do
47
46
  plugin :errors, :routing
48
47
  def initialize( appid='params-test', sspec=TEST_SEND_SPEC, rspec=TEST_RECV_SPEC )
49
48
  super
50
49
  end
51
50
  end
52
- Strelka.log.debug " new instance is: %p" % [ @app ]
53
51
  end
54
52
 
55
53
  it "doesn't alter normal responses" do
@@ -48,7 +48,7 @@ describe Strelka::App::Filters do
48
48
  super
49
49
  end
50
50
  end
51
- Strelka.log.debug " new instance is: %p, filters array: 0x%016x" %
51
+ Strelka.log.debug " App class is: %p, filters array: 0x%016x" %
52
52
  [ @app, @app.filters.object_id * 2 ]
53
53
  end
54
54
 
@@ -52,8 +52,8 @@ describe Strelka::App::Parameters do
52
52
  @app = nil
53
53
  end
54
54
 
55
- it "has a parameters Hash" do
56
- @app.parameters.should be_a( Hash )
55
+ it "has a ParamValidator" do
56
+ @app.paramvalidator.should be_a( Strelka::ParamValidator )
57
57
  end
58
58
 
59
59
  it "can declare a parameter with a validation pattern" do
@@ -61,95 +61,9 @@ describe Strelka::App::Parameters do
61
61
  param :username, /\w+/i
62
62
  end
63
63
 
64
- @app.parameters.should have( 1 ).member
65
- @app.parameters[ :username ].
66
- should include( :constraint => /(?<username>(?i-mx:\w+))/ )
64
+ @app.paramvalidator.param_names.should == [ :username ]
67
65
  end
68
66
 
69
- it "can declare a parameter with an Array validation" do
70
- @app.class_eval do
71
- param :username, [:printable, lambda {|str| str.length <= 16 }]
72
- end
73
-
74
- @app.parameters.should have( 1 ).member
75
- @app.parameters[:username][:constraint][0].should == :printable
76
- @app.parameters[:username][:constraint][1].should be_an_instance_of( Proc )
77
- end
78
-
79
- it "can declare a parameter with a Hash validation" do
80
- @app.class_eval do
81
- param :username, {'ambrel' => 'A. Hotchgah'}
82
- end
83
-
84
- @app.parameters.should have( 1 ).member
85
- @app.parameters[ :username ].
86
- should include( :constraint => {'ambrel' => 'A. Hotchgah'} )
87
- end
88
-
89
- it "can declare a parameter with a matcher validation" do
90
- @app.class_eval do
91
- param :host, :hostname
92
- end
93
-
94
- @app.parameters.should have( 1 ).member
95
- @app.parameters[ :host ].should include( :constraint => :hostname )
96
- end
97
-
98
- it "can declare a parameter with a validation pattern and a description" do
99
- @app.class_eval do
100
- param :username, /\w+/i, "The user's login"
101
- end
102
-
103
- @app.parameters.should have( 1 ).member
104
- @app.parameters[ :username ].should include( :required => false )
105
- @app.parameters[ :username ].should include( :constraint => /(?<username>(?i-mx:\w+))/ )
106
- @app.parameters[ :username ].should include( :description => "The user's login" )
107
- end
108
-
109
- it "can declare a parameter with an Array validation and a description" do
110
- @app.class_eval do
111
- param :username, ['johnny5', 'ariel', 'hotah'], "The user's login"
112
- end
113
-
114
- @app.parameters.should have( 1 ).member
115
- @app.parameters[ :username ].
116
- should include( :constraint => ['johnny5', 'ariel', 'hotah'] )
117
- @app.parameters[ :username ].should include( :description => "The user's login" )
118
- end
119
-
120
- it "can declare a parameter with just a description" do
121
- @app.class_eval do
122
- param :uuid, "UUID string"
123
- end
124
-
125
- @app.parameters.should have( 1 ).member
126
- @app.parameters[ :uuid ].should include( :description => "UUID string" )
127
- @app.parameters[ :uuid ].should include( :constraint => :uuid )
128
- end
129
-
130
- it "can declare a parameter with a validation pattern and a flag" do
131
- @app.class_eval do
132
- param :username, /\w+/i, :untaint
133
- end
134
-
135
- @app.parameters.should have( 1 ).member
136
- @app.parameters[ :username ].should include( :required => false )
137
- @app.parameters[ :username ].should include( :untaint => true )
138
- @app.parameters[ :username ].should include( :constraint => /(?<username>(?i-mx:\w+))/ )
139
- @app.parameters[ :username ].should include( :description => nil )
140
- end
141
-
142
- it "can declare a parameter with a validation Array and a flag" do
143
- @app.class_eval do
144
- param :username, ['amhel', 'hotah', 'aurelii'], :required
145
- end
146
-
147
- @app.parameters.should have( 1 ).member
148
- @app.parameters[ :username ].should include( :required => true )
149
- @app.parameters[ :username ].
150
- should include( :constraint => ['amhel', 'hotah', 'aurelii'] )
151
- @app.parameters[ :username ].should include( :description => nil )
152
- end
153
67
 
154
68
  it "inherits parameters from its superclass" do
155
69
  @app.class_eval do
@@ -157,9 +71,7 @@ describe Strelka::App::Parameters do
157
71
  end
158
72
  subapp = Class.new( @app )
159
73
 
160
- subapp.parameters.should have( 1 ).member
161
- subapp.parameters[ :username ].
162
- should include( :constraint => /(?<username>(?i-mx:\w+))/ )
74
+ subapp.paramvalidator.param_names.should == [ :username ]
163
75
  end
164
76
 
165
77
  describe "instance" do