authoritah 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/authoritah.rb CHANGED
@@ -28,6 +28,9 @@ module Authoritah
28
28
  options = args.extract_options!
29
29
  args.each {|a| options[a] = nil}
30
30
  actions = options.delete(action_identifier)
31
+ on_reject = options.delete(:on_reject) || :render_404
32
+
33
+ raise ":on_reject must be a symbol or a Proc" unless on_reject.is_a?(Symbol) || on_reject.is_a?(Proc)
31
34
 
32
35
  check_role_selectors(options)
33
36
 
@@ -35,8 +38,13 @@ module Authoritah
35
38
  role_predicate = options.to_a.first[1]
36
39
 
37
40
  controller_permissions[controller_name.to_sym] ||= PermissionSet.new
38
- controller_permissions[controller_name.to_sym] <<
39
- {:type => perm_type, :role_method => role_method, :role_predicate => role_predicate, :actions => actions ? Array(actions) : nil}
41
+ controller_permissions[controller_name.to_sym] << {
42
+ :type => perm_type,
43
+ :role_method => role_method,
44
+ :role_predicate => role_predicate,
45
+ :actions => actions ? Array(actions) : nil,
46
+ :on_reject => on_reject
47
+ }
40
48
  end
41
49
 
42
50
  def this_controllers_permissions
@@ -61,16 +69,18 @@ module Authoritah
61
69
  module InstanceMethods
62
70
 
63
71
  def check_permissions
64
- return true if permitted?(action_name.to_sym)
65
- render(:file => File.join(RAILS_ROOT, 'public', '404.html'), :status => 404)
66
- false
72
+ permitted?(action_name.to_sym)
67
73
  end
68
74
 
69
75
  protected
70
76
 
77
+ def render_404
78
+ render(:file => File.join(RAILS_ROOT, 'public', '404.html'), :status => 404)
79
+ end
80
+
71
81
  def permitted?(action)
72
82
  return true unless permissions = self.class.this_controllers_permissions
73
- permissions.permits?(self, action) && !permissions.forbids?(self, action)
83
+ permissions.permits?(self, action)
74
84
  end
75
85
  end
76
86
 
@@ -90,39 +100,52 @@ module Authoritah
90
100
  end
91
101
 
92
102
  def permits?(controller, action)
93
- apply_rules(:permit, controller, action).include?(false) == false
103
+ permitted, on_reject_action = apply_rule_chain(:permit, controller, action)
104
+ if permitted
105
+ return true
106
+ else
107
+ if on_reject_action.is_a?(Proc)
108
+ # debugger
109
+ # on_reject_action.call(controller)
110
+ controller.instance_eval(&on_reject_action)
111
+ else
112
+ controller.send(on_reject_action)
113
+ end
114
+ return false
115
+ end
94
116
  end
95
117
 
96
- def forbids?(controller, action)
97
- apply_rules(:forbid, controller, action).include?(true)
98
- end
99
-
100
118
  def permissions
101
119
  @permissions ||= []
102
120
  end
103
121
 
104
122
  protected
105
-
106
- def apply_rules(rule_type, controller, action)
107
- permissions.select{|p|
108
- p[:type] == rule_type
109
- }.select{|p|
110
- p[:actions].include?(action) || p[:actions].include?(:all)
111
- }.map do |permission|
123
+
124
+ # Returns [true, nil] if the rule chain applied without a problem.
125
+ # Returns [false, :reject_to]
126
+ def apply_rule_chain(rule_type, controller, action)
127
+ select_permissions_for(action).each do |permission|
112
128
  begin
113
- if permission[:role_predicate].is_a? Symbol
129
+ response = if permission[:role_predicate].is_a? Symbol
114
130
  controller.send(permission[:role_method]).send(permission[:role_predicate])
115
131
  elsif permission[:role_predicate].is_a? Proc
116
132
  permission[:role_predicate].call(controller.send(permission[:role_method]))
117
133
  elsif permission[:role_predicate] == nil
118
134
  controller.send(permission[:role_method])
119
- else
120
- false
121
135
  end
136
+ response = !response if permission[:type] == :forbid
137
+ return [false, permission[:on_reject]] unless response
122
138
  rescue
123
- false
139
+ return [permission[:type] == :forbid, permission[:on_reject]]
124
140
  end
125
141
  end
142
+ [true, nil]
143
+ end
144
+
145
+ def select_permissions_for(action)
146
+ permissions.select{|p|
147
+ p[:actions].include?(action) || p[:actions].include?(:all)
148
+ }
126
149
  end
127
150
  end
128
151
 
@@ -1,5 +1,5 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper'
2
-
2
+ require 'ruby-debug'
3
3
  describe Authoritah::Controller do
4
4
 
5
5
  before(:each) do
@@ -200,6 +200,9 @@ describe TestAuthorizerController, :type => :controller do
200
200
  end
201
201
  end
202
202
  context "an unauthenticated user" do
203
+ before(:each) do
204
+ controller.stubs(:current_user => false)
205
+ end
203
206
  it "should render index" do get :index; response.should render_template('index') end
204
207
  end
205
208
  end
@@ -245,15 +248,73 @@ describe TestAuthorizerController, :type => :controller do
245
248
  end
246
249
  end
247
250
 
248
- describe "overriding check_permissions" do
249
- before(:each) do
250
- TestAuthorizerController.permits(:current_user => :logged_in?)
251
- TestAuthorizerController.send(:define_method, :check_permissions) do
252
- return true if permitted?(action_name.to_sym)
253
- redirect_to root_url
254
- false
251
+ describe "specifying a different action to run on failure" do
252
+
253
+ it "should check that :on_reject is a Proc or Symbol" do
254
+ lambda do
255
+ TestAuthorizerController.permits(:current_user => :logged_in?, :on_reject => :method)
256
+ end.should_not raise_error
257
+ lambda do
258
+ TestAuthorizerController.permits(:current_user => :logged_in?, :on_reject => Proc.new {})
259
+ end.should_not raise_error
260
+ lambda do
261
+ TestAuthorizerController.permits(:current_user => :logged_in?, :on_reject => 5)
262
+ end.should raise_error
263
+ end
264
+
265
+ context "when :on_reject => :set_flash_and_redirect" do
266
+ before(:each) do
267
+ TestAuthorizerController.permits(:current_user => :logged_in?, :on_reject => :set_flash_and_redirect)
268
+ TestAuthorizerController.send(:define_method, :set_flash_and_redirect) do
269
+ flash[:error] = "You need to be logged in to do that"
270
+ redirect_to root_url
271
+ end
272
+ end
273
+ context "an unauthenticated user" do
274
+ it "should redirect to /" do
275
+ get :index
276
+ response.should redirect_to(root_url)
277
+ end
278
+ it "should set the flash" do
279
+ get :index
280
+ flash[:error].should == "You need to be logged in to do that"
281
+ end
282
+ end
283
+ end
284
+
285
+ context "when :on_reject => Proc" do
286
+ before(:each) do
287
+ TestAuthorizerController.permits(:current_user => :logged_in?, :on_reject => Proc.new { redirect_to root_url })
288
+ end
289
+ context "an unauthenticated user" do
290
+ it "should redirect to /" do
291
+ get :index
292
+ response.should redirect_to(root_url)
293
+ end
255
294
  end
256
295
  end
257
- it "should redirect to / instead of rendering /404.html" do get :index; response.should redirect_to(root_url) end
296
+
297
+ context "with multiple rules" do
298
+ before(:each) do
299
+ TestAuthorizerController.permits(:current_user => :logged_in?)
300
+ TestAuthorizerController.forbids(:current_user => :blacklisted?, :on_reject => :set_blacklisted)
301
+ TestAuthorizerController.send(:define_method, :set_blacklisted) do
302
+ flash[:error] = "You can't be blacklisted to do that"
303
+ redirect_to '/blacklisted'
304
+ end
305
+ end
306
+
307
+ context "as a blacklisted user" do
308
+ before(:each) do
309
+ controller.stubs(:current_user => stub(:logged_in? => true, :blacklisted? => true))
310
+ end
311
+ it 'should redirect to /blacklisted' do
312
+ get :index
313
+ response.should redirect_to('/blacklisted')
314
+ end
315
+ end
316
+
317
+ end
258
318
  end
319
+
259
320
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authoritah
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Steven Mohapi-Banks
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-05 00:00:00 +01:00
12
+ date: 2009-11-04 00:00:00 +00:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - ">="
22
22
  - !ruby/object:Gem::Version
23
- version: 1.2.8
23
+ version: 1.2.9
24
24
  version:
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec-rails
@@ -30,7 +30,7 @@ dependencies:
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.2.7.1
33
+ version: 1.2.9
34
34
  version:
35
35
  - !ruby/object:Gem::Dependency
36
36
  name: mocha
@@ -80,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
80
  requirements: []
81
81
 
82
82
  rubyforge_project:
83
- rubygems_version: 1.3.4
83
+ rubygems_version: 1.3.5
84
84
  signing_key:
85
85
  specification_version: 3
86
86
  summary: A really simple authorization plugin for Rails.
@@ -91,9 +91,7 @@ test_files:
91
91
  - spec/railsenv/config/boot.rb
92
92
  - spec/railsenv/config/database.yml
93
93
  - spec/railsenv/config/environment.rb
94
- - spec/railsenv/config/environments/cucumber.rb
95
94
  - spec/railsenv/config/environments/development.rb
96
- - spec/railsenv/config/environments/production.rb
97
95
  - spec/railsenv/config/environments/test.rb
98
96
  - spec/railsenv/config/initializers/backtrace_silencers.rb
99
97
  - spec/railsenv/config/initializers/inflections.rb
@@ -1,23 +0,0 @@
1
- config.cache_classes = true # This must be true for Cucumber to operate correctly!
2
-
3
- # Log error messages when you accidentally call methods on nil.
4
- config.whiny_nils = true
5
-
6
- # Show full error reports and disable caching
7
- config.action_controller.consider_all_requests_local = true
8
- config.action_controller.perform_caching = false
9
-
10
- # Disable request forgery protection in test environment
11
- config.action_controller.allow_forgery_protection = false
12
-
13
- # Tell Action Mailer not to deliver emails to the real world.
14
- # The :test delivery method accumulates sent emails in the
15
- # ActionMailer::Base.deliveries array.
16
- config.action_mailer.delivery_method = :test
17
-
18
- config.gem 'cucumber', :lib => false, :version => '>=0.3.100' unless File.directory?(File.join(Rails.root, 'vendor/plugins/cucumber'))
19
- config.gem 'webrat', :lib => false, :version => '>=0.5.0' unless File.directory?(File.join(Rails.root, 'vendor/plugins/webrat'))
20
- config.gem 'rspec', :lib => false, :version => '>=1.2.6' unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec'))
21
- config.gem 'rspec-rails', :lib => 'spec/rails', :version => '>=1.2.6' unless File.directory?(File.join(Rails.root, 'vendor/plugins/rspec-rails'))
22
-
23
- config.gem 'spork', :lib => false, :version => '>=0.5.9' unless File.directory?(File.join(Rails.root, 'vendor/plugins/spork'))
@@ -1,28 +0,0 @@
1
- # Settings specified here will take precedence over those in config/environment.rb
2
-
3
- # The production environment is meant for finished, "live" apps.
4
- # Code is not reloaded between requests
5
- config.cache_classes = true
6
-
7
- # Full error reports are disabled and caching is turned on
8
- config.action_controller.consider_all_requests_local = false
9
- config.action_controller.perform_caching = true
10
- config.action_view.cache_template_loading = true
11
-
12
- # See everything in the log (default is :info)
13
- # config.log_level = :debug
14
-
15
- # Use a different logger for distributed setups
16
- # config.logger = SyslogLogger.new
17
-
18
- # Use a different cache store in production
19
- # config.cache_store = :mem_cache_store
20
-
21
- # Enable serving of images, stylesheets, and javascripts from an asset server
22
- # config.action_controller.asset_host = "http://assets.example.com"
23
-
24
- # Disable delivery errors, bad email addresses will be ignored
25
- # config.action_mailer.raise_delivery_errors = false
26
-
27
- # Enable threaded mode
28
- # config.threadsafe!