verification 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in verification.gemspec
4
+ gemspec
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 David Heinemeier Hansson
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README ADDED
@@ -0,0 +1,34 @@
1
+ This module provides a class-level method for specifying that certain
2
+ actions are guarded against being called without certain prerequisites
3
+ being met. This is essentially a special kind of before_filter.
4
+
5
+ An action may be guarded against being invoked without certain request
6
+ parameters being set, or without certain session values existing.
7
+
8
+ When a verification is violated, values may be inserted into the flash, and
9
+ a specified redirection is triggered. If no specific action is configured,
10
+ verification failures will by default result in a 400 Bad Request response.
11
+
12
+ Usage:
13
+
14
+ class GlobalController < ActionController::Base
15
+ # Prevent the #update_settings action from being invoked unless
16
+ # the 'admin_privileges' request parameter exists. The
17
+ # settings action will be redirected to in current controller
18
+ # if verification fails.
19
+ verify :params => "admin_privileges", :only => :update_post,
20
+ :redirect_to => { :action => "settings" }
21
+
22
+ # Disallow a post from being updated if there was no information
23
+ # submitted with the post, and if there is no active post in the
24
+ # session, and if there is no "note" key in the flash. The route
25
+ # named category_url will be redirected to if verification fails.
26
+
27
+ verify :params => "post", :session => "post", "flash" => "note",
28
+ :only => :update_post,
29
+ :add_flash => { "alert" => "Failed to create your message" },
30
+ :redirect_to => :category_url
31
+
32
+ Note that these prerequisites are not business rules. They do not examine
33
+ the content of the session or the parameters. That level of validation should
34
+ be encapsulated by your domain model or helper methods in the controller.
@@ -0,0 +1,22 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the verification plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ end
14
+
15
+ desc 'Generate documentation for the verification plugin.'
16
+ Rake::RDocTask.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'Verification'
19
+ rdoc.options << '--line-numbers' << '--inline-source'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
data/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ # Include hook code here
2
+
3
+ require 'action_controller/verification'
@@ -0,0 +1,132 @@
1
+ module ActionController #:nodoc:
2
+ module Verification #:nodoc:
3
+ extend ActiveSupport::Concern
4
+
5
+ include AbstractController::Callbacks, Flash, Rendering
6
+
7
+ # This module provides a class-level method for specifying that certain
8
+ # actions are guarded against being called without certain prerequisites
9
+ # being met. This is essentially a special kind of before_filter.
10
+ #
11
+ # An action may be guarded against being invoked without certain request
12
+ # parameters being set, or without certain session values existing.
13
+ #
14
+ # When a verification is violated, values may be inserted into the flash, and
15
+ # a specified redirection is triggered. If no specific action is configured,
16
+ # verification failures will by default result in a 400 Bad Request response.
17
+ #
18
+ # Usage:
19
+ #
20
+ # class GlobalController < ActionController::Base
21
+ # # Prevent the #update_settings action from being invoked unless
22
+ # # the 'admin_privileges' request parameter exists. The
23
+ # # settings action will be redirected to in current controller
24
+ # # if verification fails.
25
+ # verify :params => "admin_privileges", :only => :update_post,
26
+ # :redirect_to => { :action => "settings" }
27
+ #
28
+ # # Disallow a post from being updated if there was no information
29
+ # # submitted with the post, and if there is no active post in the
30
+ # # session, and if there is no "note" key in the flash. The route
31
+ # # named category_url will be redirected to if verification fails.
32
+ #
33
+ # verify :params => "post", :session => "post", "flash" => "note",
34
+ # :only => :update_post,
35
+ # :add_flash => { "alert" => "Failed to create your message" },
36
+ # :redirect_to => :category_url
37
+ #
38
+ # Note that these prerequisites are not business rules. They do not examine
39
+ # the content of the session or the parameters. That level of validation should
40
+ # be encapsulated by your domain model or helper methods in the controller.
41
+ module ClassMethods
42
+ # Verify the given actions so that if certain prerequisites are not met,
43
+ # the user is redirected to a different action. The +options+ parameter
44
+ # is a hash consisting of the following key/value pairs:
45
+ #
46
+ # <tt>:params</tt>::
47
+ # a single key or an array of keys that must be in the <tt>params</tt>
48
+ # hash in order for the action(s) to be safely called.
49
+ # <tt>:session</tt>::
50
+ # a single key or an array of keys that must be in the <tt>session</tt>
51
+ # in order for the action(s) to be safely called.
52
+ # <tt>:flash</tt>::
53
+ # a single key or an array of keys that must be in the flash in order
54
+ # for the action(s) to be safely called.
55
+ # <tt>:method</tt>::
56
+ # a single key or an array of keys--any one of which must match the
57
+ # current request method in order for the action(s) to be safely called.
58
+ # (The key should be a symbol: <tt>:get</tt> or <tt>:post</tt>, for
59
+ # example.)
60
+ # <tt>:xhr</tt>::
61
+ # true/false option to ensure that the request is coming from an Ajax
62
+ # call or not.
63
+ # <tt>:add_flash</tt>::
64
+ # a hash of name/value pairs that should be merged into the session's
65
+ # flash if the prerequisites cannot be satisfied.
66
+ # <tt>:add_headers</tt>::
67
+ # a hash of name/value pairs that should be merged into the response's
68
+ # headers hash if the prerequisites cannot be satisfied.
69
+ # <tt>:redirect_to</tt>::
70
+ # the redirection parameters to be used when redirecting if the
71
+ # prerequisites cannot be satisfied. You can redirect either to named
72
+ # route or to the action in some controller.
73
+ # <tt>:render</tt>::
74
+ # the render parameters to be used when the prerequisites cannot be satisfied.
75
+ # <tt>:only</tt>::
76
+ # only apply this verification to the actions specified in the associated
77
+ # array (may also be a single value).
78
+ # <tt>:except</tt>::
79
+ # do not apply this verification to the actions specified in the associated
80
+ # array (may also be a single value).
81
+ def verify(options={})
82
+ before_filter :only => options[:only], :except => options[:except] do
83
+ verify_action options
84
+ end
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def verify_action(options) #:nodoc:
91
+ if prereqs_invalid?(options)
92
+ flash.update(options[:add_flash]) if options[:add_flash]
93
+ response.headers.merge!(options[:add_headers]) if options[:add_headers]
94
+ apply_remaining_actions(options) unless performed?
95
+ end
96
+ end
97
+
98
+ def prereqs_invalid?(options) # :nodoc:
99
+ verify_presence_of_keys_in_hash_flash_or_params(options) ||
100
+ verify_method(options) ||
101
+ verify_request_xhr_status(options)
102
+ end
103
+
104
+ def verify_presence_of_keys_in_hash_flash_or_params(options) # :nodoc:
105
+ [*options[:params] ].find { |v| v && params[v.to_sym].nil? } ||
106
+ [*options[:session]].find { |v| session[v].nil? } ||
107
+ [*options[:flash] ].find { |v| flash[v].nil? }
108
+ end
109
+
110
+ def verify_method(options) # :nodoc:
111
+ [*options[:method]].all? { |v| request.request_method_symbol != v.to_sym } if options[:method]
112
+ end
113
+
114
+ def verify_request_xhr_status(options) # :nodoc:
115
+ request.xhr? != options[:xhr] unless options[:xhr].nil?
116
+ end
117
+
118
+ def apply_redirect_to(redirect_to_option) # :nodoc:
119
+ (redirect_to_option.is_a?(Symbol) && redirect_to_option != :back) ? self.__send__(redirect_to_option) : redirect_to_option
120
+ end
121
+
122
+ def apply_remaining_actions(options) # :nodoc:
123
+ case
124
+ when options[:render] ; render(options[:render])
125
+ when options[:redirect_to] ; redirect_to(apply_redirect_to(options[:redirect_to]))
126
+ else head(:bad_request)
127
+ end
128
+ end
129
+ end
130
+ end
131
+
132
+ ActionController::Base.send :include, ActionController::Verification
@@ -0,0 +1 @@
1
+ require 'action_controller/verification'
@@ -0,0 +1,18 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'active_support'
4
+ require 'action_controller'
5
+ require File.dirname(__FILE__) + '/../lib/action_controller/verification'
6
+
7
+ SharedTestRoutes = ActionDispatch::Routing::RouteSet.new
8
+ SharedTestRoutes.draw do
9
+ match '/:controller(/:action(/:id))'
10
+ end
11
+
12
+ ActionController::Base.send :include, SharedTestRoutes.url_helpers
13
+
14
+ module ActionController
15
+ class TestCase
16
+ setup { @routes = SharedTestRoutes }
17
+ end
18
+ end
@@ -0,0 +1,288 @@
1
+ require 'test_helper'
2
+
3
+ class VerificationTestController < ActionController::Base
4
+ use Rack::MethodOverride
5
+
6
+ verify :only => :guarded_one, :params => "one",
7
+ :add_flash => { :error => 'unguarded' },
8
+ :redirect_to => { :action => "unguarded" }
9
+
10
+ verify :only => :guarded_two, :params => %w( one two ),
11
+ :redirect_to => { :action => "unguarded" }
12
+
13
+ verify :only => :guarded_with_flash, :params => "one",
14
+ :add_flash => { :notice => "prereqs failed" },
15
+ :redirect_to => { :action => "unguarded" }
16
+
17
+ verify :only => :guarded_in_session, :session => "one",
18
+ :redirect_to => { :action => "unguarded" }
19
+
20
+ verify :only => [:multi_one, :multi_two], :session => %w( one two ),
21
+ :redirect_to => { :action => "unguarded" }
22
+
23
+ verify :only => :guarded_by_method, :method => :post,
24
+ :redirect_to => { :action => "unguarded" }
25
+
26
+ verify :only => :guarded_by_xhr, :xhr => true,
27
+ :redirect_to => { :action => "unguarded" }
28
+
29
+ verify :only => :guarded_by_not_xhr, :xhr => false,
30
+ :redirect_to => { :action => "unguarded" }
31
+
32
+ before_filter :unconditional_redirect, :only => :two_redirects
33
+ verify :only => :two_redirects, :method => :post,
34
+ :redirect_to => { :action => "unguarded" }
35
+
36
+ verify :only => :must_be_post, :method => :post, :render => { :status => 405, :text => "Must be post" }, :add_headers => { "Allow" => "POST" }
37
+
38
+ verify :only => :must_be_put, :method => :put, :render => { :status => 405, :text => "Must be put" }, :add_headers => { "Allow" => "PUT" }
39
+
40
+ verify :only => :guarded_one_for_named_route_test, :params => "one",
41
+ :redirect_to => :foo_url
42
+
43
+ verify :only => :no_default_action, :params => "santa"
44
+
45
+ verify :only => :guarded_with_back, :method => :post,
46
+ :redirect_to => :back
47
+
48
+ def guarded_one
49
+ render :text => "#{params[:one]}"
50
+ end
51
+
52
+ def guarded_one_for_named_route_test
53
+ render :text => "#{params[:one]}"
54
+ end
55
+
56
+ def guarded_with_flash
57
+ render :text => "#{params[:one]}"
58
+ end
59
+
60
+ def guarded_two
61
+ render :text => "#{params[:one]}:#{params[:two]}"
62
+ end
63
+
64
+ def guarded_in_session
65
+ render :text => "#{session["one"]}"
66
+ end
67
+
68
+ def multi_one
69
+ render :text => "#{session["one"]}:#{session["two"]}"
70
+ end
71
+
72
+ def multi_two
73
+ render :text => "#{session["two"]}:#{session["one"]}"
74
+ end
75
+
76
+ def guarded_by_method
77
+ render :text => "#{request.method}"
78
+ end
79
+
80
+ def guarded_by_xhr
81
+ render :text => "#{request.xhr?}"
82
+ end
83
+
84
+ def guarded_by_not_xhr
85
+ render :text => "#{request.xhr?}"
86
+ end
87
+
88
+ def unguarded
89
+ render :text => "#{params[:one]}"
90
+ end
91
+
92
+ def two_redirects
93
+ render :nothing => true
94
+ end
95
+
96
+ def must_be_post
97
+ render :text => "Was a post!"
98
+ end
99
+
100
+ def must_be_put
101
+ render :text => "Was a put!"
102
+ end
103
+
104
+ def guarded_with_back
105
+ render :text => "#{params[:one]}"
106
+ end
107
+
108
+ def no_default_action
109
+ # Will never run
110
+ end
111
+
112
+ protected
113
+
114
+ def unconditional_redirect
115
+ redirect_to :action => "unguarded"
116
+ end
117
+ end
118
+
119
+ class VerificationTest < ActionController::TestCase
120
+ tests ::VerificationTestController
121
+
122
+ def test_using_symbol_back_with_no_referrer
123
+ assert_raise(ActionController::RedirectBackError) { get :guarded_with_back }
124
+ end
125
+
126
+ def test_using_symbol_back_redirects_to_referrer
127
+ @request.env["HTTP_REFERER"] = "/foo"
128
+ get :guarded_with_back
129
+ assert_redirected_to '/foo'
130
+ end
131
+
132
+ def test_no_deprecation_warning_for_named_route
133
+ assert_not_deprecated do
134
+ with_routing do |set|
135
+ set.draw do
136
+ match 'foo', :to => 'test#foo', :as => :foo
137
+ match 'verification_test/:action', :to => ::VerificationTestController
138
+ end
139
+ get :guarded_one_for_named_route_test, :two => "not one"
140
+ assert_redirected_to '/foo'
141
+ end
142
+ end
143
+ end
144
+
145
+ def test_guarded_one_with_prereqs
146
+ get :guarded_one, :one => "here"
147
+ assert_equal "here", @response.body
148
+ end
149
+
150
+ def test_guarded_one_without_prereqs
151
+ get :guarded_one
152
+ assert_redirected_to :action => "unguarded"
153
+ assert_equal 'unguarded', flash[:error]
154
+ end
155
+
156
+ def test_guarded_with_flash_with_prereqs
157
+ get :guarded_with_flash, :one => "here"
158
+ assert_equal "here", @response.body
159
+ assert flash.empty?
160
+ end
161
+
162
+ def test_guarded_with_flash_without_prereqs
163
+ get :guarded_with_flash
164
+ assert_redirected_to :action => "unguarded"
165
+ assert_equal "prereqs failed", flash[:notice]
166
+ end
167
+
168
+ def test_guarded_two_with_prereqs
169
+ get :guarded_two, :one => "here", :two => "there"
170
+ assert_equal "here:there", @response.body
171
+ end
172
+
173
+ def test_guarded_two_without_prereqs_one
174
+ get :guarded_two, :two => "there"
175
+ assert_redirected_to :action => "unguarded"
176
+ end
177
+
178
+ def test_guarded_two_without_prereqs_two
179
+ get :guarded_two, :one => "here"
180
+ assert_redirected_to :action => "unguarded"
181
+ end
182
+
183
+ def test_guarded_two_without_prereqs_both
184
+ get :guarded_two
185
+ assert_redirected_to :action => "unguarded"
186
+ end
187
+
188
+ def test_unguarded_with_params
189
+ get :unguarded, :one => "here"
190
+ assert_equal "here", @response.body
191
+ end
192
+
193
+ def test_unguarded_without_params
194
+ get :unguarded
195
+ assert @response.body.blank?
196
+ end
197
+
198
+ def test_guarded_in_session_with_prereqs
199
+ get :guarded_in_session, {}, "one" => "here"
200
+ assert_equal "here", @response.body
201
+ end
202
+
203
+ def test_guarded_in_session_without_prereqs
204
+ get :guarded_in_session
205
+ assert_redirected_to :action => "unguarded"
206
+ end
207
+
208
+ def test_multi_one_with_prereqs
209
+ get :multi_one, {}, "one" => "here", "two" => "there"
210
+ assert_equal "here:there", @response.body
211
+ end
212
+
213
+ def test_multi_one_without_prereqs
214
+ get :multi_one
215
+ assert_redirected_to :action => "unguarded"
216
+ end
217
+
218
+ def test_multi_two_with_prereqs
219
+ get :multi_two, {}, "one" => "here", "two" => "there"
220
+ assert_equal "there:here", @response.body
221
+ end
222
+
223
+ def test_multi_two_without_prereqs
224
+ get :multi_two
225
+ assert_redirected_to :action => "unguarded"
226
+ end
227
+
228
+ def test_guarded_by_method_with_prereqs
229
+ post :guarded_by_method
230
+ assert_equal "POST", @response.body
231
+ end
232
+
233
+ def test_guarded_by_method_without_prereqs
234
+ get :guarded_by_method
235
+ assert_redirected_to :action => "unguarded"
236
+ end
237
+
238
+ def test_guarded_by_xhr_with_prereqs
239
+ xhr :post, :guarded_by_xhr
240
+ assert_equal "true", @response.body
241
+ end
242
+
243
+ def test_guarded_by_xhr_without_prereqs
244
+ get :guarded_by_xhr
245
+ assert_redirected_to :action => "unguarded"
246
+ end
247
+
248
+ def test_guarded_by_not_xhr_with_prereqs
249
+ get :guarded_by_not_xhr
250
+ assert_equal "false", @response.body
251
+ end
252
+
253
+ def test_guarded_by_not_xhr_without_prereqs
254
+ xhr :post, :guarded_by_not_xhr
255
+ assert_redirected_to :action => "unguarded"
256
+ end
257
+
258
+ def test_guarded_post_and_calls_render_succeeds
259
+ post :must_be_post
260
+ assert_equal "Was a post!", @response.body
261
+ end
262
+
263
+ def test_guarded_put_and_calls_render_succeeds
264
+ put :must_be_put
265
+ assert_equal "Was a put!", @response.body
266
+ end
267
+
268
+ def test_guarded_post_with_put_params_and_calls_render_succeeds
269
+ post :must_be_put, '_method' => 'put'
270
+ assert_equal "Was a put!", @response.body
271
+ end
272
+
273
+ def test_default_failure_should_be_a_bad_request
274
+ post :no_default_action
275
+ assert_response :bad_request
276
+ end
277
+
278
+ def test_guarded_post_and_calls_render_fails_and_sets_allow_header
279
+ get :must_be_post
280
+ assert_response 405
281
+ assert_equal "Must be post", @response.body
282
+ assert_equal "POST", @response.headers["Allow"]
283
+ end
284
+
285
+ def test_second_redirect
286
+ assert_nothing_raised { get :two_redirects }
287
+ end
288
+ end
@@ -0,0 +1,20 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "verification"
5
+ s.version = "1.0.1"
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["David Heinemeier Hansson"]
8
+ s.email = ["david@loudthinking.com"]
9
+ s.homepage = "https://rubygems.org/gems/verification"
10
+ s.summary = %q{Verify preconditions for Rails actions}
11
+ s.description = %q{Verify preconditions for Rails actions}
12
+
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = ["lib"]
17
+
18
+ s.add_dependency('activesupport', '~>3.0.0')
19
+ s.add_dependency('actionpack', '~>3.0.0')
20
+ end
metadata ADDED
@@ -0,0 +1,110 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: verification
3
+ version: !ruby/object:Gem::Version
4
+ hash: 21
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 1
10
+ version: 1.0.1
11
+ platform: ruby
12
+ authors:
13
+ - David Heinemeier Hansson
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-11-16 00:00:00 -05:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: activesupport
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 7
30
+ segments:
31
+ - 3
32
+ - 0
33
+ - 0
34
+ version: 3.0.0
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: actionpack
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ hash: 7
46
+ segments:
47
+ - 3
48
+ - 0
49
+ - 0
50
+ version: 3.0.0
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ description: Verify preconditions for Rails actions
54
+ email:
55
+ - david@loudthinking.com
56
+ executables: []
57
+
58
+ extensions: []
59
+
60
+ extra_rdoc_files: []
61
+
62
+ files:
63
+ - .gitignore
64
+ - Gemfile
65
+ - MIT-LICENSE
66
+ - README
67
+ - Rakefile
68
+ - init.rb
69
+ - lib/action_controller/verification.rb
70
+ - lib/verification.rb
71
+ - test/test_helper.rb
72
+ - test/verification_test.rb
73
+ - verification.gemspec
74
+ has_rdoc: true
75
+ homepage: https://rubygems.org/gems/verification
76
+ licenses: []
77
+
78
+ post_install_message:
79
+ rdoc_options: []
80
+
81
+ require_paths:
82
+ - lib
83
+ required_ruby_version: !ruby/object:Gem::Requirement
84
+ none: false
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ hash: 3
89
+ segments:
90
+ - 0
91
+ version: "0"
92
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
+ none: false
94
+ requirements:
95
+ - - ">="
96
+ - !ruby/object:Gem::Version
97
+ hash: 3
98
+ segments:
99
+ - 0
100
+ version: "0"
101
+ requirements: []
102
+
103
+ rubyforge_project:
104
+ rubygems_version: 1.3.7
105
+ signing_key:
106
+ specification_version: 3
107
+ summary: Verify preconditions for Rails actions
108
+ test_files:
109
+ - test/test_helper.rb
110
+ - test/verification_test.rb