authoritah 0.0.5 → 0.1.0

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