strelka 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 61bf9e26b28c2ed2b22d5b69924c2882ec985a54
4
+ data.tar.gz: 2c112fd724573c6bef02a4d24b8af0cf59af660e
5
+ SHA512:
6
+ metadata.gz: e00fbbbda4e9f473311fe1de9e5d5dd6f0297e15835bfc9b487b932e3e5047abcaa3344ce87f76d1fb2c6008736a23918743375818108165af3f3c483b15b6be
7
+ data.tar.gz: 50452d6a4e88827c1a42f562bd576a38c3d8565eb53e4ff0d243c0ec44e57420ebec3f0a200184e76aaaaff96add79504053e994d76cec0551f9686c03851707
checksums.yaml.gz.sig ADDED
Binary file
data.tar.gz.sig CHANGED
Binary file
data/ChangeLog CHANGED
@@ -1,11 +1,143 @@
1
+ 2013-02-25 Michael Granger <ged@FaerieMUD.org>
2
+
3
+ * lib/strelka/paramvalidator.rb:
4
+ Fix API documentation
5
+ [5471a055ac2e] [tip]
6
+
7
+ * lib/strelka/app/restresources.rb:
8
+ Add some documentation to the REST Resources plugin
9
+ [bfbbcdf9ebe8]
10
+
11
+ * lib/strelka/paramvalidator.rb:
12
+ Remove accidentally-committed code.
13
+ [0875b2988d81]
14
+
15
+ 2013-02-22 Michael Granger <ged@FaerieMUD.org>
16
+
17
+ * lib/strelka/httprequest.rb, spec/strelka/httprequest_spec.rb:
18
+ Guard against malformed URI query
19
+ [2e56a22dac4a]
20
+
21
+ * lib/strelka/httpresponse.rb:
22
+ Whitespace fix
23
+ [ebe06cfc1695]
24
+
25
+ 2013-02-06 Michael Granger <ged@FaerieMUD.org>
26
+
27
+ * lib/strelka/app/auth.rb, spec/strelka/app/auth_spec.rb:
28
+ Fix multiple permission criteria in the auth plugin (fixes #2)
29
+ [d661773e0781] [github/master]
30
+
31
+ 2013-02-01 Michael Granger <ged@FaerieMUD.org>
32
+
33
+ * History.rdoc, lib/strelka/app/restresources.rb,
34
+ lib/strelka/paramvalidator.rb,
35
+ spec/strelka/app/restresources_spec.rb,
36
+ spec/strelka/paramvalidator_spec.rb:
37
+ Remove pending status from specs for multiple parameters support
38
+
39
+ This was apparently implemented (by me) in 49716850bd29. Fixes #1.
40
+ [2c41e18bc237]
41
+
42
+ 2013-01-29 Michael Granger <ged@FaerieMUD.org>
43
+
44
+ * lib/strelka/app/parameters.rb, lib/strelka/paramvalidator.rb,
45
+ spec/strelka/app/parameters_spec.rb,
46
+ spec/strelka/paramvalidator_spec.rb:
47
+ Add a paramvalidator constraint for JSON fields
48
+ [ac11b12f9366] [github/no-notes-auto-vivify]
49
+
50
+ 2013-01-25 Michael Granger <ged@FaerieMUD.org>
51
+
52
+ * lib/strelka/httprequest.rb, lib/strelka/httpresponse.rb,
53
+ spec/strelka/app/filters_spec.rb, spec/strelka/httprequest_spec.rb:
54
+ Remove HTTP{Request,Response}#notes multi-level autovivification
55
+ [0dc702f6eacc]
56
+
57
+ * bin/strelka:
58
+ Add support for --requires to bin/strelka
59
+ [c844fb419c83]
60
+
61
+ * lib/strelka.rb, lib/strelka/app/parameters.rb,
62
+ spec/strelka/app/parameters_spec.rb,
63
+ spec/strelka/app/restresources_spec.rb:
64
+ Allow declaration of parameters with block constraints
65
+ [afb6cec9add0]
66
+
67
+ * .rvm.gems, .tm_properties, Rakefile,
68
+ lib/strelka/app/restresources.rb, lib/strelka/paramvalidator.rb,
69
+ spec/strelka/app/restresources_spec.rb:
70
+ Modify the restresources app plugin for new versions of Sequel
71
+ [543c22d3050e]
72
+
73
+ 2013-01-24 Michael Granger <ged@FaerieMUD.org>
74
+
75
+ * lib/strelka/app/routing.rb, spec/strelka/app/routing_spec.rb:
76
+ Fix the routing plugin to super with a block like the other plugins
77
+ [9ac7a036f54a]
78
+
79
+ 2013-01-18 Michael Granger <ged@FaerieMUD.org>
80
+
81
+ * .pryrc:
82
+ Fix the .pryrc for recent versions of pry
83
+ [779190d1cc55]
84
+
85
+ 2013-01-09 Michael Granger <ged@FaerieMUD.org>
86
+
87
+ * .rvm.gems:
88
+ Update rvm gemset file
89
+ [2bedace701fe]
90
+
91
+ 2013-01-02 Michael Granger <ged@FaerieMUD.org>
92
+
93
+ * lib/strelka/paramvalidator.rb:
94
+ Remove spurious return in ParamValidator#[]=
95
+ [39c9459daa02]
96
+
97
+ 2013-01-02 Mahlon E. Smith <mahlon@martini.nu>
98
+
99
+ * lib/strelka/paramvalidator.rb, spec/strelka/paramvalidator_spec.rb:
100
+ Revalidate parameters when using the index operator.
101
+ [1d71e22f5f6e]
102
+
103
+ 2012-12-27 Michael Granger <ged@FaerieMUD.org>
104
+
105
+ * .hgtags:
106
+ Added tag v0.1.0 for changeset 943a0502da20
107
+ [43c3f7dddf0d]
108
+
109
+ * .hgsigs:
110
+ Added signature for changeset a6be71c3d94d
111
+ [943a0502da20] [v0.1.0]
112
+
113
+ * History.rdoc, lib/strelka.rb:
114
+ Bump the minor version, update history.
115
+ [a6be71c3d94d]
116
+
117
+ * spec/strelka/app_spec.rb:
118
+ Fix a spec for newer versions of Mongrel2
119
+ [ee1b3bcf1664]
120
+
1
121
  2012-11-02 Michael Granger <ged@FaerieMUD.org>
2
122
 
123
+ * bin/strelka:
124
+ Add --version to the command line tool
125
+ [4581498edfaa]
126
+
127
+ * lib/strelka/paramvalidator.rb:
128
+ Fix documentation
129
+ [6523f90b76ac]
130
+
131
+ * lib/strelka/app/parameters.rb:
132
+ Remove accidentally-committed require.
133
+ [e98f2b302f1d]
134
+
3
135
  * lib/strelka/app/parameters.rb, lib/strelka/app/restresources.rb,
4
136
  lib/strelka/mixins.rb, lib/strelka/paramvalidator.rb,
5
137
  lib/strelka/plugins.rb, spec/strelka/paramvalidator_spec.rb:
6
138
  Rewrite ParamValidator to simplify, remove dependency on
7
139
  FormValidator.
8
- [49716850bd29] [github/master, tip]
140
+ [49716850bd29]
9
141
 
10
142
  2012-11-02 Mahlon E. Smith <mahlon@martini.nu>
11
143
 
data/History.rdoc CHANGED
@@ -1,3 +1,18 @@
1
+ == v0.2.0 [2013-02-01] Michael Granger <ged@FaerieMUD.org>
2
+
3
+ - Fixes for Ruby 2.0.
4
+ - Fix API documentation
5
+ - Guard against malformed URI query
6
+ - Fix multiple permission criteria in the auth plugin (fixes #2)
7
+ - Add a paramvalidator constraint for JSON fields
8
+ - Remove HTTP{Request,Response}#notes multi-level autovivification
9
+ - Add support for --requires to bin/strelka
10
+ - Allow declaration of parameters with block constraints
11
+ - Modify the restresources app plugin for new versions of Sequel
12
+ - Fix the routing plugin to super with a block like the other plugins
13
+ - Revalidate parameters when using ParamValidator#[].
14
+
15
+
1
16
  == v0.1.0 [2012-11-02] Michael Granger <ged@FaerieMUD.org>
2
17
 
3
18
  - Add --version to the command line tool
data/Rakefile CHANGED
@@ -27,7 +27,7 @@ hoespec = Hoe.spec 'strelka' do
27
27
  self.dependency 'highline', '~> 1.6'
28
28
  self.dependency 'inversion', '~> 0.11'
29
29
  self.dependency 'loggability', '~> 0.4'
30
- self.dependency 'mongrel2', '~> 0.34'
30
+ self.dependency 'mongrel2', '~> 0.35'
31
31
  self.dependency 'pluginfactory', '~> 1.0'
32
32
  self.dependency 'sysexits', '~> 1.1'
33
33
  self.dependency 'trollop', '~> 2.0'
data/bin/strelka CHANGED
@@ -100,11 +100,14 @@ class Strelka::CLICommand
100
100
  collect {|name,lvl| name.to_s }.
101
101
  join( ', ' )
102
102
  command_table = self.make_command_table
103
+ commands = self.available_commands
103
104
 
104
105
  @option_parser = Trollop::Parser.new do
105
106
  banner "Manage Strelka apps"
106
107
  version( Strelka.version_string(true) )
107
108
 
109
+ stop_on( commands )
110
+
108
111
  text ''
109
112
  command_table.each {|line| text(line) }
110
113
  text ''
@@ -113,6 +116,8 @@ class Strelka::CLICommand
113
116
  opt :config, "Specify the config file to load.", :type => :string
114
117
  opt :datadir, "Override the Strelka data directory.", :type => :string,
115
118
  :short => :D
119
+ opt :requires, "Specify additional libraries to require.", :type => :strings,
120
+ :short => :r
116
121
  text ''
117
122
 
118
123
  text 'Other Options:'
@@ -259,6 +264,8 @@ class Strelka::CLICommand
259
264
  def discover_command( *args )
260
265
  header "Searching for Strelka applications..."
261
266
 
267
+ self.load_additional_requires
268
+
262
269
  paths = Strelka::App.discover_paths
263
270
  if paths.empty?
264
271
  message "None found."
@@ -298,6 +305,9 @@ class Strelka::CLICommand
298
305
  apps = Strelka::App.load( path )
299
306
  Strelka.load_config( self.options.config ) if self.options.config
300
307
  self.log.debug " loaded: %p" % [ apps ]
308
+
309
+ self.load_additional_requires
310
+
301
311
  apps.first.run
302
312
  end
303
313
  help :start, "Start a Strelka app"
@@ -325,6 +335,8 @@ class Strelka::CLICommand
325
335
  Strelka::App.load( apppath )
326
336
  end
327
337
 
338
+ self.load_additional_requires
339
+
328
340
  message " dumping config:"
329
341
  $stdout.puts Configurability.default_config.dump
330
342
  end
@@ -385,6 +397,17 @@ class Strelka::CLICommand
385
397
  end
386
398
 
387
399
 
400
+ ### Load any requires added to the command via the '-r' option.
401
+ def load_additional_requires
402
+ return unless self.options.requires
403
+
404
+ self.log.debug " loading additional requires: %p" % [ self.options.requires ]
405
+ self.options.requires.each do |lib|
406
+ require( lib )
407
+ end
408
+ end
409
+
410
+
388
411
  #
389
412
  # Utility methods
390
413
  #
data/lib/strelka.rb CHANGED
@@ -24,10 +24,10 @@ module Strelka
24
24
  log_as :strelka
25
25
 
26
26
  # Library version constant
27
- VERSION = '0.1.0'
27
+ VERSION = '0.2.0'
28
28
 
29
29
  # Version-control revision constant
30
- REVISION = %q$Revision: a6be71c3d94d $
30
+ REVISION = %q$Revision: afb6cec9add0 $
31
31
 
32
32
  require 'strelka/constants'
33
33
  require 'strelka/exceptions'
@@ -286,8 +286,8 @@ module Strelka::App::Auth
286
286
  @positive_auth_criteria = {}
287
287
  @negative_auth_criteria = {}
288
288
 
289
- @positive_perms_criteria = {}
290
- @negative_perms_criteria = {}
289
+ @positive_perms_criteria = []
290
+ @negative_perms_criteria = []
291
291
 
292
292
 
293
293
  ##
@@ -409,17 +409,19 @@ module Strelka::App::Auth
409
409
  ### +pattern+. The +pattern+ is either a String or a Regexp which is tested against
410
410
  ### {the request's #app_path}[rdoc-ref:Strelka::HTTPRequest#app_path]. The +perms+ should
411
411
  ### be Symbols which indicate a set of permission types that must have been granted
412
- ### in order to carry out the request. The block should also return one or more
413
- ### permissions (as Symbols) if the request should undergo authorization, or nil
414
- ### if it should not.
412
+ ### in order to carry out the request. The block, if given, should evaluate to +true+
413
+ ### if the request should undergo authorization, or false if it should not.
415
414
  ### *NOTE:* using this declaration inverts the default security policy of
416
415
  ### restricting access to all requests.
417
416
  def require_perms_for( pattern=nil, *perms, &block )
418
- block ||= Proc.new { perms }
417
+ block ||= Proc.new {
418
+ self.log.debug " using default perms: %p" % [ perms ]
419
+ true
420
+ }
419
421
 
420
422
  pattern.gsub!( %r{^/+|/+$}, '' ) if pattern.respond_to?( :gsub! )
421
423
  self.log.debug " adding require_perms (%p) for %p" % [ perms, pattern ]
422
- self.positive_perms_criteria[ pattern ] = block
424
+ self.positive_perms_criteria << [ pattern, block, perms ]
423
425
  end
424
426
 
425
427
 
@@ -435,7 +437,7 @@ module Strelka::App::Auth
435
437
 
436
438
  pattern.gsub!( %r{^/+|/+$}, '' ) if pattern.respond_to?( :gsub! )
437
439
  self.log.debug " adding no_auth for %p" % [ pattern ]
438
- self.negative_perms_criteria[ pattern ] = block
440
+ self.negative_perms_criteria << [ pattern, block ]
439
441
  end
440
442
 
441
443
  end # module ClassMethods
@@ -502,7 +504,7 @@ module Strelka::App::Auth
502
504
  ### +nil+ if the request didn't require authentication.
503
505
  def provide_authorization( credentials, request )
504
506
  provider = self.auth_provider
505
- perms = self.required_perms_for( request )
507
+ perms = self.perms_required_for( request )
506
508
  self.log.debug "Perms required: %p" % [ perms ]
507
509
  provider.authorize( credentials, request, perms ) unless perms.empty?
508
510
  end
@@ -550,7 +552,7 @@ module Strelka::App::Auth
550
552
 
551
553
  ### Gather the set of permissions that apply to the specified +request+ and return
552
554
  ### them.
553
- def required_perms_for( request )
555
+ def perms_required_for( request )
554
556
  self.log.debug "Gathering required perms for: %s %s" % [ request.verb, request.app_path ]
555
557
 
556
558
  # Return the empty set if any negative auth criteria match
@@ -565,6 +567,7 @@ module Strelka::App::Auth
565
567
  # Apply positive auth criteria
566
568
  return self.union_positive_perms_criteria( request )
567
569
  end
570
+ alias_method :required_perms_for, :perms_required_for
568
571
 
569
572
 
570
573
  #########
@@ -617,8 +620,8 @@ module Strelka::App::Auth
617
620
  perms = []
618
621
 
619
622
  self.log.debug " positive perm criteria: %p" % [ self.class.positive_perms_criteria ]
620
- self.class.positive_perms_criteria.each do |pattern, block|
621
- newperms = self.request_matches_criteria( request, pattern, &block ) or next
623
+ self.class.positive_perms_criteria.each do |pattern, block, newperms|
624
+ next unless self.request_matches_criteria( request, pattern, &block )
622
625
  newperms = Array( newperms )
623
626
  newperms << self.default_permission if newperms.empty?
624
627
 
@@ -93,10 +93,16 @@ module Strelka::App::Parameters
93
93
  ### Declare a parameter with the specified +name+ that will be validated using the given
94
94
  ### +constraint+. The +constraint+ can be any of the types supported by
95
95
  ### Strelka::ParamValidator.
96
- def param( name, *args )
96
+ def param( name, *args, &block )
97
97
  self.log.debug "New param %p" % [ name ]
98
98
  self.log.debug " adding parameter %p to %p" % [ name, self.paramvalidator ]
99
- self.paramvalidator.add( name, *args )
99
+ self.paramvalidator.add( name, *args, &block )
100
+ end
101
+
102
+
103
+ ### Add a 'builtin' constraint type with the specified +name+.
104
+ def add_param_type( name, &block )
105
+
100
106
  end
101
107
 
102
108
 
@@ -43,14 +43,28 @@ require 'strelka/app' unless defined?( Strelka::App )
43
43
  # parameters[Strelka::App::Parameters] plugins, and will load them
44
44
  # automatically if they haven't been already.
45
45
  #
46
- # Stuff left to do:
46
+ # Goals:
47
+ #
48
+ # [√] Composite resources generated from associations
49
+ # [ ] Honor If-unmodified-since and If-match headers
50
+ # [ ] Caching support (ETag, If-modified-since)
51
+ # [ ] Means of tailoring responses for requests for which the response
52
+ # isn't clearly specified in the RFC (DELETE /resource)
53
+ # [ ] Sequel plugin for adding links to serialized representations
54
+ #
55
+ # == Caveats / Known Problems
56
+ #
57
+ # * Dataset methods declared using the 'subset' declaration don't allow the
58
+ # introspection necessary for automatically building routes, so you have
59
+ # to declare them as normal methods in a dataset module:
60
+ #
61
+ # dataset_module do
62
+ # def by_name( string )
63
+ # filter(:name => string)
64
+ # end
65
+ # end
66
+ #
47
67
  #
48
- # * Composite resources generated from associations
49
- # * Honor If-unmodified-since and If-match headers
50
- # * Caching support (ETag, If-modified-since)
51
- # * Means of tailoring responses for requests for which the response
52
- # isn't clearly specified in the RFC (DELETE /resource)
53
- # * Sequel plugin for adding links to serialized representations
54
68
  module Strelka::App::RestResources
55
69
  extend Strelka::Plugin
56
70
 
@@ -238,7 +252,7 @@ module Strelka::App::RestResources
238
252
  # Add validations for limit, offset, and order parameters
239
253
  req.params.add :limit, :integer
240
254
  req.params.add :offset, :integer
241
- req.params.add :order, colre
255
+ req.params.add :order, colre, :multiple
242
256
 
243
257
  finish_with( HTTP::BAD_REQUEST, req.params.error_messages.join("\n") ) unless
244
258
  req.params.okay?
@@ -444,23 +458,14 @@ module Strelka::App::RestResources
444
458
  ### Add routes for any associations +rsrcobj+ has as composite resources.
445
459
  def add_composite_resource_handlers( route_prefix, rsrcobj, options )
446
460
 
447
- # Add a method for each dataset method that only has a single argument
448
- # :TODO: Support multiple args? (customers/by_city_state/{city}/{state})
449
- rsrcobj.dataset_methods.each do |name, proc|
450
- if proc.parameters.length > 1
451
- self.log.debug " skipping dataset method %p: more than 1 argument" % [ name ]
452
- next
453
- end
461
+ # Add methods declared by (user-declared) dataset modules.
462
+ ds_mods = rsrcobj.dataset_method_modules.select do |mod|
463
+ mod.is_a?( Sequel::Model::DatasetModule ) || mod.name.nil?
464
+ end.each
454
465
 
455
- # Use the name of the dataset block's parameter
456
- # :TODO: Handle the case where the parameter name doesn't match a column
457
- # or a parameter-type more gracefully.
458
- unless proc.parameters.empty?
459
- param = proc.parameters.first[1]
460
- route = "%s/%s/:%s" % [ route_prefix, name, param ]
461
- self.log.debug " route for dataset method %s: %s" % [ name, route ]
462
- self.add_dataset_read_handler( route, rsrcobj, name, param, options )
463
- end
466
+ ds_mods.each do |mod|
467
+ self.log.debug " adding dataset methods declared by %p" % [ mod ]
468
+ self.add_dataset_module_routes( route_prefix, rsrcobj, mod, options )
464
469
  end
465
470
 
466
471
  # Add composite service routes for each association
@@ -476,14 +481,44 @@ module Strelka::App::RestResources
476
481
  end
477
482
 
478
483
 
484
+ ### Add routes for the methods declared in the dataset module +mod+.
485
+ def add_dataset_module_routes( route_prefix, rsrcobj, mod, options )
486
+ self.log.debug "Adding dataset module routes."
487
+
488
+ mod.instance_methods.each do |methname|
489
+ meth = mod.instance_method( methname )
490
+ self.log.debug " instance_method: %p" % [ meth ]
491
+
492
+ route = "%s/%s" % [ route_prefix, methname ]
493
+ params = []
494
+
495
+ # Add a route placeholder for each parameter of the dataset method
496
+ meth.parameters.each do |type, param|
497
+ self.log.debug " adding parameter placeholder to the route for %s parameter %p" %
498
+ [ type, param ]
499
+ route << "/:%s" % [ param ]
500
+ params << param
501
+ end
502
+
503
+ self.log.debug " route for dataset method %s: %s" % [ methname, route ]
504
+ self.add_dataset_read_handler( route, rsrcobj, methname, params, options )
505
+ end
506
+
507
+ self.log.debug " done with dataset module routes."
508
+ end
509
+
510
+
479
511
  ### Add a GET route for the dataset method +dsname+ for the given +rsrcobj+ at the
480
512
  ### given +path+.
481
- def add_dataset_read_handler( path, rsrcobj, dsname, param, options )
513
+ def add_dataset_read_handler( path, rsrcobj, dsname, params, options )
482
514
  self.log.debug "Adding dataset method read handler: %s" % [ path ]
483
515
 
484
- config = rsrcobj.db_schema[ param ] or
485
- raise ArgumentError, "no such column %p for %p" % [ param, rsrcobj ]
486
- param( param, config[:type] )
516
+ # Only need to declare a parameter if the dataset method has one
517
+ params.each do |paramname|
518
+ config = rsrcobj.db_schema[ paramname ] or
519
+ raise ArgumentError, "no such column %p for %p" % [ paramname, rsrcobj ]
520
+ param( paramname, config[:type] )
521
+ end
487
522
 
488
523
  self.add_route( :GET, path, options ) do |req|
489
524
  self.log.debug "Resource dataset GET request for dataset %s on %p" %
@@ -491,10 +526,9 @@ module Strelka::App::RestResources
491
526
  finish_with( HTTP::BAD_REQUEST, req.params.error_messages.join("\n") ) unless
492
527
  req.params.okay?
493
528
 
494
- # Get the parameter and make the dataset
495
- res = req.response
496
- arg = req.params[ param ]
497
- dataset = rsrcobj.send( dsname, arg )
529
+ # Get the dataset, either with a parameter or without one
530
+ args = req.params.values_at( *params )
531
+ dataset = rsrcobj.send( dsname, *args )
498
532
  self.log.debug " dataset is: %p" % [ dataset ]
499
533
 
500
534
  # Apply offset and limit if they're present
@@ -507,6 +541,7 @@ module Strelka::App::RestResources
507
541
  # Fetch and return the records as JSON or YAML
508
542
  # :TODO: Handle other mediatypes
509
543
  self.log.debug " returning collection: %s" % [ dataset.sql ]
544
+ res = req.response
510
545
  res.for( :json, :yaml ) { dataset.all }
511
546
  res.for( :text ) { Sequel::PrettyTable.string(dataset) }
512
547