strelka 0.0.1.pre177 → 0.0.1.pre184

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.
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