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.
- data/ChangeLog +111 -16
- data/Manifest.txt +8 -8
- data/Rakefile +3 -3
- data/bin/leash +51 -28
- data/examples/{auth-demo.rb → apps/auth-demo} +3 -3
- data/examples/{auth-demo2.rb → apps/auth-demo2} +0 -0
- data/examples/{sessions-demo.rb → apps/sessions-demo} +0 -0
- data/examples/config.yml +5 -1
- data/examples/{examples.css → static/examples.css} +0 -0
- data/examples/{examples.html → static/examples.html} +0 -0
- data/examples/{auth-form.tmpl → templates/auth-form.tmpl} +0 -0
- data/examples/{auth-success.tmpl → templates/auth-success.tmpl} +0 -0
- data/examples/{layout.tmpl → templates/layout.tmpl} +0 -0
- data/lib/strelka/app/auth.rb +18 -8
- data/lib/strelka/app/errors.rb +3 -2
- data/lib/strelka/app/filters.rb +2 -0
- data/lib/strelka/app/negotiation.rb +2 -0
- data/lib/strelka/app/parameters.rb +18 -140
- data/lib/strelka/app/plugins.rb +84 -26
- data/lib/strelka/app/restresources.rb +26 -18
- data/lib/strelka/app/routing.rb +8 -2
- data/lib/strelka/app/sessions.rb +7 -0
- data/lib/strelka/app/templating.rb +1 -1
- data/lib/strelka/app.rb +25 -1
- data/lib/strelka/constants.rb +3 -1
- data/lib/strelka/paramvalidator.rb +251 -74
- data/lib/strelka/session/default.rb +1 -1
- data/spec/strelka/app/auth_spec.rb +37 -0
- data/spec/strelka/app/errors_spec.rb +0 -2
- data/spec/strelka/app/filters_spec.rb +1 -1
- data/spec/strelka/app/parameters_spec.rb +4 -92
- data/spec/strelka/app/plugins_spec.rb +64 -2
- data/spec/strelka/app/restresources_spec.rb +3 -0
- data/spec/strelka/app/routing_spec.rb +5 -5
- data/spec/strelka/paramvalidator_spec.rb +294 -385
- data.tar.gz.sig +0 -0
- metadata +126 -46
- 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
|
-
# #
|
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
|
-
#
|
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
|
-
#
|
54
|
-
#
|
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
|
-
|
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
|
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
|
-
@
|
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 "
|
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 = (
|
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" %
|
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:
|
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
|
-
|
685
|
-
|
686
|
-
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
698
|
-
|
699
|
-
|
700
|
-
|
701
|
-
|
702
|
-
|
703
|
-
|
704
|
-
|
705
|
-
|
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
|
#######
|
@@ -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
|
@@ -52,8 +52,8 @@ describe Strelka::App::Parameters do
|
|
52
52
|
@app = nil
|
53
53
|
end
|
54
54
|
|
55
|
-
it "has a
|
56
|
-
@app.
|
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.
|
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.
|
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
|