authorization-san 1.0.2 → 2.0.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/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- (c) 2009 Fingertips, Manfred Stienstra <m.stienstra@fngtps.com>
1
+ (c) 2011 Fingertips, Manfred Stienstra <m.stienstra@fngtps.com>
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to
@@ -49,29 +49,29 @@ module Authorization
49
49
  def allow_access(*args, &block)
50
50
  unless self.respond_to?(:access_allowed_for)
51
51
  self.class_inheritable_accessor(:access_allowed_for)
52
+ self.access_allowed_for = {}.with_indifferent_access
52
53
  send(:protected, :access_allowed_for, :access_allowed_for=)
53
54
  end
54
- self.access_allowed_for ||= HashWithIndifferentAccess.new
55
+
55
56
  if args.first.kind_of?(Hash) || args.empty?
56
- self.access_allowed_for[:all] ||= []
57
- self.access_allowed_for[:all] << {
58
- :directives => args.first || {},
59
- :block => block
60
- }
57
+ directives = args.first || {}
58
+ roles = ['all']
61
59
  else
62
60
  directives = args.extract_options!
63
61
  roles = args.flatten
64
- if roles.delete(:authenticated) or roles.delete('authenticated')
65
- roles = [:all] if roles.empty?
66
- directives[:authenticated] = true
67
- end
68
- roles.each do |role|
69
- self.access_allowed_for[role.to_s] ||= []
70
- self.access_allowed_for[role.to_s] << {
71
- :directives => directives,
72
- :block => block
73
- }
74
- end
62
+ end
63
+
64
+ if roles.delete(:authenticated) or roles.delete('authenticated')
65
+ directives[:authenticated] = true
66
+ roles = ['all'] if roles.empty?
67
+ end
68
+
69
+ roles.each do |role|
70
+ self.access_allowed_for[role] ||= []
71
+ self.access_allowed_for[role] << {
72
+ :directives => directives,
73
+ :block => block
74
+ }
75
75
  end
76
76
  end
77
77
  end
@@ -2,132 +2,107 @@ module Authorization
2
2
  module BlockAccess
3
3
  protected
4
4
 
5
+ def die_if_undefined #:nodoc:
6
+ if !self.respond_to?(:access_allowed_for) or access_allowed_for.nil?
7
+ raise ArgumentError, "Please specify access control using `allow_access' in the controller"
8
+ end
9
+ end
10
+
5
11
  # Block access to all actions in the controller, designed to be used as a <tt>before_filter</tt>.
12
+ #
6
13
  # class ApplicationController < ActionController::Base
7
14
  # before_filter :block_access
8
15
  # end
16
+ #
17
+ # When there are no rules to allow the client on the requested resource it calls
18
+ # +access_forbidden+. You can override +access_forbidden+ to halt the filter
19
+ # chain or do something else.
20
+ #
21
+ # The +block_access+ method returns +true+ when access was granted. It returns
22
+ # the same thing as +access_forbidden+ when access was forbidden.
9
23
  def block_access
10
24
  die_if_undefined
11
25
  unless @authenticated.nil?
12
- # Find the user's roles
13
- roles = []
14
- roles << @authenticated.role if @authenticated.respond_to?(:role)
15
- access_allowed_for.keys.each do |role|
16
- roles << role.to_s if @authenticated.respond_to?("#{role}?") and @authenticated.send("#{role}?")
26
+ if @authenticated.respond_to?(:role)
27
+ return true if _access_allowed?(params, @authenticated.role, @authenticated)
17
28
  end
18
- # Check if any of the roles give her access
19
- roles.each do |role|
20
- return true if access_allowed?(params, role, @authenticated)
29
+ access_allowed_for.keys.each do |role|
30
+ if @authenticated.respond_to?("#{role}?") and @authenticated.send("#{role}?")
31
+ return true if _access_allowed?(params, role, @authenticated)
32
+ end
21
33
  end
22
34
  end
23
- return true if access_allowed?(params, :all, @authenticated)
24
- access_forbidden
35
+ _access_allowed?(params, :all, @authenticated) ? true : access_forbidden
25
36
  end
26
37
 
27
- # Checks if access is allowed for the params, role and authenticated user.
28
- # access_allowed?({:action => :show, :id => 1}, :admin, @authenticated)
29
- def access_allowed?(params, role, authenticated=nil)
30
- die_if_undefined
31
- if (rules = access_allowed_for[role]).nil?
32
- logger.debug(" \e[31mCan't find rules for `#{role}'\e[0m")
33
- return false
38
+ def _matches_action?(directives, action) #:nodoc:
39
+ if directives[:only]
40
+ directives[:only] == action or (directives[:only].respond_to?(:include?) and directives[:only].include?(action))
41
+ elsif directives[:except]
42
+ directives[:except] != action and !(directives[:except].respond_to?(:include?) and directives[:except].include?(action))
43
+ else
44
+ true
34
45
  end
35
- !rules.detect do |rule|
36
- if !action_allowed_by_rule?(rule, params, role) or !resource_allowed_by_rule?(rule, params, role, authenticated) or !block_allowed_by_rule?(rule)
37
- logger.debug(" \e[31mAccess DENIED by RULE #{rule.inspect} FOR `#{role}'\e[0m")
38
- false
39
- else
40
- logger.debug(" \e[32mAccess GRANTED by RULE #{rule.inspect} FOR `#{role}'\e[0m")
41
- true
42
- end
43
- end.nil?
44
46
  end
45
-
46
- # <tt>access_forbidden</tt> is called by <tt>block_access</tt> when access is forbidden. This method does
47
- # nothing by default. Make sure you return <tt>false</tt> from the method if you want to halt the filter
48
- # chain.
49
- def access_forbidden
47
+
48
+ def _matches_scope?(scope, params, authenticated) #:nodoc:
49
+ return true if scope.nil?
50
+ scope_id = params["#{scope}_id"].to_i
51
+ object_id = authenticated.send(scope).id.to_i
52
+ (object_id > 0) and (scope_id == object_id)
53
+ rescue NoMethodError
50
54
  false
51
55
  end
56
+
57
+ def _matches_user_resource?(run, params, authenticated) #:nodoc:
58
+ return true unless run
59
+ authenticated_id = authenticated ? authenticated.id.to_i : 0
60
+ (authenticated_id > 0) and (params[:id].to_i == authenticated_id)
61
+ end
62
+
63
+ def _matches_authenticated_requirement?(run, authenticated) #:nodoc:
64
+ return true unless run
65
+ authenticated
66
+ end
52
67
 
53
- # Checks if a certain action can be accessed by the role.
54
- # If you want to check for <tt>action_allowed?</tt>, <tt>resource_allowed?</tt> and <tt>block_allowed?</tt>
55
- # use <tt>access_allowed?</tt>.
56
- # action_allowed?({:action => :show, :id => 1}, :editor)
57
- def action_allowed?(params, role=:all)
58
- die_if_undefined
59
- return false if (rules = access_allowed_for[role]).nil?
60
- !rules.detect { |rule| action_allowed_by_rule?(rule, params, role) }.nil?
68
+ def _block_is_successful?(block) #:nodoc:
69
+ block ? block.bind(self).call : true
61
70
  end
62
71
 
63
- def action_allowed_by_rule?(rule, params, role) #:nodoc:
64
- return false if (action = params[:action]).nil?
72
+ def _access_allowed_with_rule?(rule, params, role, authenticated) #:nodoc:
73
+ action = params[:action].to_sym
65
74
  directives = rule[:directives]
66
- return false if directives[:only].kind_of?(Array) and !directives[:only].include?(action.to_sym)
67
- return false if directives[:only].kind_of?(Symbol) and directives[:only] != action.to_sym
68
- return false if directives[:except].kind_of?(Array) and directives[:except].include?(action.to_sym)
69
- return false if directives[:except].kind_of?(Symbol) and directives[:except] == action.to_sym
70
- true
75
+ _matches_action?(directives, action) and
76
+ _matches_scope?(directives[:scope], params, authenticated) and
77
+ _matches_user_resource?(directives[:user_resource], params, authenticated) and
78
+ _matches_authenticated_requirement?(directives[:authenticated], authenticated) and
79
+ _block_is_successful?(rule[:block])
71
80
  end
72
81
 
73
- # Checks if the resource indicated by the params can be accessed by user.
74
- # If you want to check for <tt>action_allowed?</tt>, <tt>resource_allowed?</tt> and <tt>block_allowed?</tt>
75
- # use <tt>access_allowed?</tt>.
76
- # resource_allowed?({:id => 1, :organization_id => 12}, :guest, @authenticated)
77
- def resource_allowed?(params, role=:all, user=nil)
78
- user ||= @authenticated
82
+ def _access_allowed?(params, role, authenticated=nil) #:nodoc:
79
83
  die_if_undefined
80
- return false if (rules = access_allowed_for[role]).nil?
81
- !rules.detect { |rule| resource_allowed_by_rule?(rule, params, role, user) }.nil?
82
- end
83
-
84
- def resource_allowed_by_rule?(rule, params, role, user) #:nodoc:
85
- directives = rule[:directives]
86
- if directives[:authenticated]
87
- return false unless user
88
- end
89
- begin
90
- if directives[:user_resource]
91
- return false if params[:id].nil? or user.id.nil?
92
- return false if params[:id].to_i != user.id.to_i
93
- end
94
- rescue NoMethodError
95
- end
96
- begin
97
- if scope = directives[:scope]
98
- assoc_id = params["#{scope}_id"].to_i
99
- begin
100
- object_id = user.send(scope).id.to_i
101
- rescue NoMethodError
102
- return false
84
+ if rules = access_allowed_for[role]
85
+ rules.each do |rule|
86
+ if _access_allowed_with_rule?(rule, params, role, authenticated)
87
+ logger.debug(" \e[32mAccess GRANTED by RULE #{rule.inspect} FOR `#{role}'\e[0m")
88
+ return true
89
+ else
90
+ logger.debug(" \e[31mAccess DENIED by RULE #{rule.inspect} FOR `#{role}'\e[0m")
103
91
  end
104
- return false if assoc_id.nil? or object_id.nil?
105
- return false if assoc_id != object_id
106
92
  end
107
- rescue NoMethodError
93
+ else
94
+ logger.debug(" \e[31mCan't find rules for `#{role}'\e[0m")
108
95
  end
109
- true
110
- end
111
-
112
- # Checks if the blocks associated with the rules doesn't stop the user from acessing the resource.
113
- # If you want to check for <tt>action_allowed?</tt>, <tt>resource_allowed?</tt> and <tt>block_allowed?</tt>
114
- # use <tt>access_allowed?</tt>.
115
- # block_allowed?(:guest)
116
- def block_allowed?(role)
117
- die_if_undefined
118
- return false if (rules = access_allowed_for[role]).nil?
119
- !rules.detect { |rule| block_allowed_by_rule?(rule) }.nil?
120
- end
121
-
122
- def block_allowed_by_rule?(rule) #:nodoc:
123
- return false if !rule[:block].nil? and !rule[:block].bind(self).call
124
- true
96
+ false
125
97
  end
126
98
 
127
- def die_if_undefined #:nodoc:
128
- if !self.respond_to?(:access_allowed_for) or access_allowed_for.nil?
129
- raise ArgumentError, "Please specify access control using `allow_access' in the controller"
130
- end
99
+ # <tt>access_forbidden</tt> is called by <tt>block_access</tt> when access is forbidden. This method does
100
+ # nothing by default. Make sure you return <tt>false</tt> from the method if you want to halt the filter
101
+ # chain.
102
+ def access_forbidden
103
+ false
131
104
  end
132
105
  end
133
- end
106
+ end
107
+
108
+ require 'authorization/deprecated'
@@ -0,0 +1,84 @@
1
+ module Authorization
2
+ module BlockAccess
3
+ protected
4
+ # Checks if a certain action can be accessed by the role.
5
+ # If you want to check for <tt>action_allowed?</tt>, <tt>resource_allowed?</tt> and <tt>block_allowed?</tt>
6
+ # use <tt>access_allowed?</tt>.
7
+ # action_allowed?({:action => :show, :id => 1}, :editor)
8
+ def action_allowed?(params, role=:all)
9
+ ::ActiveSupport::Deprecation.warn("action_allowed? has been deprecated.", caller)
10
+ die_if_undefined
11
+ return false if (rules = access_allowed_for[role]).nil?
12
+ !rules.detect { |rule| action_allowed_by_rule?(rule, params, role) }.nil?
13
+ end
14
+
15
+ def action_allowed_by_rule?(rule, params, role) #:nodoc:
16
+ ::ActiveSupport::Deprecation.warn("action_allowed_by_rule? has been deprecated.", caller)
17
+ return false if (action = params[:action]).nil?
18
+ directives = rule[:directives]
19
+ return false if directives[:only].kind_of?(Array) and !directives[:only].include?(action.to_sym)
20
+ return false if directives[:only].kind_of?(Symbol) and directives[:only] != action.to_sym
21
+ return false if directives[:except].kind_of?(Array) and directives[:except].include?(action.to_sym)
22
+ return false if directives[:except].kind_of?(Symbol) and directives[:except] == action.to_sym
23
+ true
24
+ end
25
+
26
+ # Checks if the resource indicated by the params can be accessed by user.
27
+ # If you want to check for <tt>action_allowed?</tt>, <tt>resource_allowed?</tt> and <tt>block_allowed?</tt>
28
+ # use <tt>access_allowed?</tt>.
29
+ # resource_allowed?({:id => 1, :organization_id => 12}, :guest, @authenticated)
30
+ def resource_allowed?(params, role=:all, user=nil)
31
+ ::ActiveSupport::Deprecation.warn("resource_allowed? has been deprecated.", caller)
32
+ user ||= @authenticated
33
+ die_if_undefined
34
+ return false if (rules = access_allowed_for[role]).nil?
35
+ !rules.detect { |rule| resource_allowed_by_rule?(rule, params, role, user) }.nil?
36
+ end
37
+
38
+ def resource_allowed_by_rule?(rule, params, role, user) #:nodoc:
39
+ ::ActiveSupport::Deprecation.warn("resource_allowed_by_rule? has been deprecated.", caller)
40
+ directives = rule[:directives]
41
+ if directives[:authenticated]
42
+ return false unless user
43
+ end
44
+ begin
45
+ if directives[:user_resource]
46
+ return false if params[:id].nil? or user.id.nil?
47
+ return false if params[:id].to_i != user.id.to_i
48
+ end
49
+ rescue NoMethodError
50
+ end
51
+ begin
52
+ if scope = directives[:scope]
53
+ assoc_id = params["#{scope}_id"].to_i
54
+ begin
55
+ object_id = user.send(scope).id.to_i
56
+ rescue NoMethodError
57
+ return false
58
+ end
59
+ return false if assoc_id.nil? or object_id.nil?
60
+ return false if assoc_id != object_id
61
+ end
62
+ rescue NoMethodError
63
+ end
64
+ true
65
+ end
66
+
67
+ # Checks if the blocks associated with the rules doesn't stop the user from acessing the resource.
68
+ # If you want to check for <tt>action_allowed?</tt>, <tt>resource_allowed?</tt> and <tt>block_allowed?</tt>
69
+ # use <tt>access_allowed?</tt>.
70
+ # block_allowed?(:guest)
71
+ def block_allowed?(role)
72
+ ::ActiveSupport::Deprecation.warn("block_allowed? has been deprecated.", caller)
73
+ die_if_undefined
74
+ return false if (rules = access_allowed_for[role]).nil?
75
+ !rules.detect { |rule| block_allowed_by_rule?(rule) }.nil?
76
+ end
77
+
78
+ def block_allowed_by_rule?(rule) #:nodoc:
79
+ ::ActiveSupport::Deprecation.warn("block_allowed_by_rule? has been deprecated.", caller)
80
+ return false if !rule[:block].nil? and !rule[:block].bind(self).call
81
+ true
82
+ end
83
+ end
84
+ end
@@ -1,13 +1,17 @@
1
- require File.expand_path('../../test_helper', __FILE__)
1
+ require 'test_helper'
2
2
 
3
3
  require 'controllers/all'
4
4
  require 'models/resource'
5
5
 
6
6
  class BehaviourTest < ActionController::TestCase
7
7
  test "access is denied for nonexistant actions without an access rule" do
8
- tests UsersController, :authenticated => Resource.new(:role => :tester, :id => 1)
9
- get :unknown, :id => 1
10
- assert_response :forbidden
8
+ begin
9
+ tests UsersController, :authenticated => Resource.new(:role => :tester, :id => 1)
10
+ get :unknown, :id => 1
11
+ assert_response :forbidden
12
+ rescue AbstractController::ActionNotFound # Rails 3 behaves diffently to missing methods
13
+ assert true
14
+ end
11
15
  end
12
16
 
13
17
  test "roles are properly checked" do
@@ -151,6 +155,12 @@ class BehaviourTest < ActionController::TestCase
151
155
  assert_response :ok
152
156
  end
153
157
 
158
+ class ActionController::Base
159
+ class << self
160
+ attr_accessor :_routes
161
+ end
162
+ end
163
+
154
164
  private
155
165
 
156
166
  def tests(controller, options={})
@@ -158,9 +168,15 @@ class BehaviourTest < ActionController::TestCase
158
168
  @response = ActionController::TestResponse.new
159
169
  @controller ||= controller.new rescue nil
160
170
 
171
+ if defined?(ActionDispatch)
172
+ @routes = ActionDispatch::Routing::RouteSet.new
173
+ @routes.draw { match ':controller(/:action(/:id(.:format)))' }
174
+ @routes.finalize!
175
+ controller._routes = @routes
176
+ end
177
+
161
178
  @controller.request = @request
162
179
  @controller.params = {}
163
- @controller.send(:initialize_current_url)
164
180
 
165
181
  @controller.authenticated = options[:authenticated]
166
182
  end
@@ -0,0 +1,127 @@
1
+ require 'test_helper'
2
+
3
+ require 'models/resource'
4
+ require 'helpers/methods'
5
+
6
+ class DeprecatedTest < ActiveSupport::TestCase
7
+ include Authorization::BlockAccess
8
+ include MethodsHelpers
9
+
10
+ test "action_allowed? sanity" do
11
+ @access_allowed_for = {
12
+ :admin => [{
13
+ :directives => {}
14
+ }],
15
+ :editor => [{
16
+ :directives => {:only => :index}
17
+ }],
18
+ :complex => [
19
+ {:directives => {:only => :index}},
20
+ {:directives => {:only => :show}}
21
+ ],
22
+ :all => [{
23
+ :directives => {:only => :listing}
24
+ }]
25
+ }
26
+ assert_action_allowed({
27
+ [:admin, :index] => true,
28
+ [:admin, :show] => true,
29
+ [:admin, :unknown] => true,
30
+ [:editor, :unknown] => false,
31
+ [:editor, :index] => true,
32
+ [:all, :index] => false,
33
+ [:all, :unknown] => false,
34
+ [:all, :listing] => true,
35
+ [:complex, :index] => true,
36
+ [:complex, :show] => true,
37
+ [:complex, :unknown] => false
38
+ })
39
+ end
40
+
41
+ test "action_allowed? sanity with directives" do
42
+ @access_allowed_for = {:all => [{:directives => {}}] }
43
+ assert_action_allowed({
44
+ [:admin, :index] => false,
45
+ [:all, :show] => true,
46
+ [:unknown, :show] => false
47
+ })
48
+ end
49
+
50
+ test "action_allowed? sanity without directives" do
51
+ @access_allowed_for = {}
52
+ assert_action_allowed({
53
+ [:admin, :index] => false,
54
+ [:all, :show] => false,
55
+ [:show, :unknown] => false
56
+ })
57
+ end
58
+
59
+ test "action_allowed? breaks when no rules are defined" do
60
+ @access_allowed_for = nil
61
+ params = HashWithIndifferentAccess.new :action => :something
62
+ assert_raises(ArgumentError) { action_allowed?(params, :something) }
63
+ end
64
+
65
+ test "resource_allowed? sanity with :authenticated directive" do
66
+ @access_allowed_for = {
67
+ :all => [{
68
+ :directives => {:authenticated => true}
69
+ }]
70
+ }
71
+ assert !resource_allowed?({}, :admin, nil)
72
+ assert !resource_allowed?({}, :admin, true)
73
+ assert resource_allowed?({}, :all, true)
74
+ assert resource_allowed?({:action => :edit}, :all, true)
75
+ end
76
+
77
+ test "resource_allowed? sanity with :user_resource directive" do
78
+ @access_allowed_for = {
79
+ :user => [{
80
+ :directives => {:only => [:index, :show], :user_resource => true}
81
+ }]
82
+ }
83
+ assert_resource_allowed({
84
+ [{}, :admin, {}] => false,
85
+ [{:id => 1}, :admin, {:id => 1}] => false,
86
+ [{}, :admin, {:id => 1}] => false,
87
+ [{:id => 1}, :admin, {}] => false,
88
+ [{}, :user, {}] => false,
89
+ [{:id => 1}, :user, {:id => 1}] => true,
90
+ [{:id => 2}, :user, {:id => 1}] => false,
91
+ [{:id => 1}, :user, {:id => 2}] => false,
92
+ [{}, :user, {:id => 1}] => false,
93
+ [{:id => 1}, :user, {}] => false,
94
+ })
95
+ end
96
+
97
+ test "resource_allowed? sanity with :scope directive" do
98
+ @access_allowed_for = {
99
+ :user => [{
100
+ :directives => {:only => [:index, :show], :scope => :organization}
101
+ }]
102
+ }
103
+ assert_resource_allowed({
104
+ [{}, :admin, {}] => false,
105
+ [{:organization_id => 1}, :admin, {:organization => Resource.new({:id => 1})}] => false,
106
+ [{}, :admin, {:organization => Resource.new({:id => 1})}] => false,
107
+ [{:organization_id => 1}, :admin, {}] => false,
108
+ [{}, :user, {}] => false,
109
+ [{:organization_id => 1}, :user, {:organization => Resource.new({:id => 1})}] => true,
110
+ [{}, :user, {:organization => Resource.new({:id => 1})}] => false,
111
+ [{:organization_id => 1}, :user, {}] => false,
112
+ [{:organization_id => 2}, :user, {:organization => Resource.new({:id => 1})}] => false,
113
+ [{:organization_id => 1}, :user, {:organization => Resource.new({:id => 2})}] => false,
114
+ })
115
+ end
116
+
117
+ test "block_allowed? sanity" do
118
+ @access_allowed_for = {
119
+ :admin => [{:block => self.class.instance_method(:do_true)}],
120
+ :all => [{:block => self.class.instance_method(:do_false)}]
121
+ }
122
+ assert_block_allowed({
123
+ :admin => true,
124
+ :all => false
125
+ })
126
+ end
127
+ end
@@ -1,146 +1,13 @@
1
- require File.expand_path('../../test_helper', __FILE__)
1
+ require 'test_helper'
2
2
 
3
3
  require 'models/resource'
4
+ require 'helpers/methods'
4
5
 
5
- class MethodsTest < ActiveSupport::TestCase
6
+ class BlockAccessTest < ActiveSupport::TestCase
6
7
  include Authorization::BlockAccess
7
- attr_accessor :params, :access_allowed_for
8
+ include MethodsHelpers
8
9
 
9
- def logger
10
- @logger ||= Logger.new('/dev/null')
11
- end
12
-
13
- def do_false
14
- false
15
- end
16
-
17
- def do_true
18
- true
19
- end
20
-
21
- def test_action_allowed
22
- @access_allowed_for = {
23
- :admin => [{
24
- :directives => {}
25
- }],
26
- :editor => [{
27
- :directives => {:only => :index}
28
- }],
29
- :complex => [
30
- {:directives => {:only => :index}},
31
- {:directives => {:only => :show}}
32
- ],
33
- :all => [{
34
- :directives => {:only => :listing}
35
- }]
36
- }
37
- assert_action_allowed({
38
- [:admin, :index] => true,
39
- [:admin, :show] => true,
40
- [:admin, :unknown] => true,
41
- [:editor, :unknown] => false,
42
- [:editor, :index] => true,
43
- [:all, :index] => false,
44
- [:all, :unknown] => false,
45
- [:all, :listing] => true,
46
- [:complex, :index] => true,
47
- [:complex, :show] => true,
48
- [:complex, :unknown] => false
49
- })
50
- end
51
-
52
- def test_action_allowed_open
53
- @access_allowed_for = {:all => [{:directives => {}}] }
54
- assert_action_allowed({
55
- [:admin, :index] => false,
56
- [:all, :show] => true,
57
- [:unknown, :show] => false
58
- })
59
- end
60
-
61
- def test_action_allowed_closed
62
- @access_allowed_for = {}
63
- assert_action_allowed({
64
- [:admin, :index] => false,
65
- [:all, :show] => false,
66
- [:show, :unknown] => false
67
- })
68
- end
69
-
70
- def test_action_allowed_nil
71
- @access_allowed_for = nil
72
- params = HashWithIndifferentAccess.new :action => :something
73
- assert_raises(ArgumentError) { action_allowed?(params, :something) }
74
- end
75
-
76
- def test_resource_allowed_user_resource
77
- @access_allowed_for = {
78
- :user => [{
79
- :directives => {:only => [:index, :show], :user_resource => true}
80
- }]
81
- }
82
- assert_resource_allowed({
83
- [{}, :admin, {}] => false,
84
- [{:id => 1}, :admin, {:id => 1}] => false,
85
- [{}, :admin, {:id => 1}] => false,
86
- [{:id => 1}, :admin, {}] => false,
87
- [{}, :user, {}] => false,
88
- [{:id => 1}, :user, {:id => 1}] => true,
89
- [{:id => 2}, :user, {:id => 1}] => false,
90
- [{:id => 1}, :user, {:id => 2}] => false,
91
- [{}, :user, {:id => 1}] => false,
92
- [{:id => 1}, :user, {}] => false,
93
- })
94
- end
95
-
96
- def test_resource_allowed_scope
97
- @access_allowed_for = {
98
- :user => [{
99
- :directives => {:only => [:index, :show], :scope => :organization}
100
- }]
101
- }
102
- assert_resource_allowed({
103
- [{}, :admin, {}] => false,
104
- [{:organization_id => 1}, :admin, {:organization => Resource.new({:id => 1})}] => false,
105
- [{}, :admin, {:organization => Resource.new({:id => 1})}] => false,
106
- [{:organization_id => 1}, :admin, {}] => false,
107
- [{}, :user, {}] => false,
108
- [{:organization_id => 1}, :user, {:organization => Resource.new({:id => 1})}] => true,
109
- [{}, :user, {:organization => Resource.new({:id => 1})}] => false,
110
- [{:organization_id => 1}, :user, {}] => false,
111
- [{:organization_id => 2}, :user, {:organization => Resource.new({:id => 1})}] => false,
112
- [{:organization_id => 1}, :user, {:organization => Resource.new({:id => 2})}] => false,
113
- })
114
- end
115
-
116
- def test_resource_allowed_authenticated
117
- @access_allowed_for = {
118
- :all => [{
119
- :directives => {:authenticated => true}
120
- }]
121
- }
122
- assert !resource_allowed?({}, :admin, nil)
123
- assert !resource_allowed?({}, :admin, true)
124
- assert resource_allowed?({}, :all, true)
125
- assert resource_allowed?({:action => :edit}, :all, true)
126
- end
127
-
128
- def test_block_allowed
129
- @access_allowed_for = {
130
- :admin => [{:block => MethodsTest.instance_method(:do_true)}],
131
- :all => [{:block => MethodsTest.instance_method(:do_false)}]
132
- }
133
- assert_block_allowed({
134
- :admin => true,
135
- :all => false
136
- })
137
- end
138
-
139
- def test_access_forbidden
140
- assert_equal false, access_forbidden
141
- end
142
-
143
- def test_block_access
10
+ test "block_access sanity" do
144
11
  @access_allowed_for = {
145
12
  :admin => [{
146
13
  :directives => {}
@@ -150,11 +17,11 @@ class MethodsTest < ActiveSupport::TestCase
150
17
  }],
151
18
  :blocked_guest => [{
152
19
  :directives => {:only => :index},
153
- :block => MethodsTest.instance_method(:do_false)
20
+ :block => self.class.instance_method(:do_false)
154
21
  }],
155
22
  :open_guest => [{
156
23
  :directives => {:only => :index},
157
- :block => MethodsTest.instance_method(:do_true)
24
+ :block => self.class.instance_method(:do_true)
158
25
  }],
159
26
  :complex => [
160
27
  {:directives => {:only => :index}},
@@ -183,70 +50,174 @@ class MethodsTest < ActiveSupport::TestCase
183
50
  })
184
51
  end
185
52
 
186
- def test_block_access_closed
53
+ test "block_access breaks when no rules are defined" do
54
+ @access_allowed_for = nil
55
+ assert_raises(ArgumentError) { block_access }
56
+ end
57
+
58
+ test "access is denied when there are no rules" do
187
59
  @access_allowed_for = {}
188
- assert_equal false, block_access
60
+ assert !block_access
189
61
  end
190
62
 
191
- def test_block_access_nil
192
- @access_allowed_for = nil
193
- assert_raises(ArgumentError) { block_access }
63
+ test "access is granted when authenticated has role and accessor and a rule matches accessor" do
64
+ @authenticated = Resource.new(:role => 'user', :'special?' => true)
65
+ set_rules(:special => [{:directives => {}}])
66
+ set_params(:action => :new)
67
+ assert block_access
194
68
  end
195
69
 
196
- def test_block_access_on_object_with_role_and_accessors_defined
197
- @access_allowed_for = {:special => [{
198
- :directives => {}
199
- }]}
200
- @authenticated = Resource.new :role => 'user', :'special?' => true
201
- @params = HashWithIndifferentAccess.new :action => :new
70
+ test "access is granted when authenticated has role and accessor and a rule matches role" do
71
+ @authenticated = Resource.new(:role => 'user', :'special?' => true)
72
+ set_rules(:user => [{:directives => {}}])
73
+ set_params(:action => :new)
74
+ assert block_access
75
+ end
76
+
77
+ test "access is denied when authenticated has role and accessor and NO rule matches" do
78
+ @authenticated = Resource.new(:role => 'user', :'special?' => true)
79
+ set_rules(:admin => [{:directives => {}}])
80
+ set_params(:action => :new)
202
81
  assert !block_access
203
82
  end
204
83
 
205
- def test_block_access_on_object_with_multiple_block_accessors_defined
84
+ test "access is granted when authenticated has multiple accessors and a rule matches" do
206
85
  @access_allowed_for = {:special => [{
207
86
  :directives => {}
208
87
  }]}
209
- @authenticated = Resource.new :'special?' => true, :'admin?' => true
210
- @params = HashWithIndifferentAccess.new :action => :new
211
- assert !block_access
88
+ @authenticated = Resource.new(:'special?' => true, :'admin?' => true)
89
+ @params = { :action => :new }.with_indifferent_access
90
+ assert block_access
212
91
  end
92
+ end
93
+
94
+ class AccessByRuleTest < ActiveSupport::TestCase
95
+ include Authorization::BlockAccess
96
+ include MethodsHelpers
213
97
 
214
- def test_block_access_on_object_with_accessor_dined_on_role
215
- @access_allowed_for = {:user => [{
216
- :directives => {}
217
- }]}
218
- @authenticated = Resource.new :role => 'user', :'special?' => true
219
- @params = HashWithIndifferentAccess.new :action => :new
220
- assert !block_access
98
+ test "matches action when there are no restrictions on action" do
99
+ assert _matches_action?({}, :new)
100
+ end
101
+
102
+ test "matches action when there are no restrictions on action and no action" do
103
+ assert _matches_action?({}, nil)
221
104
  end
222
105
 
223
- private
106
+ test "matches action when there are inclusive restrictions on action (array)" do
107
+ assert _matches_action?({:only => [:index, :new, :create]}, :index)
108
+ end
109
+
110
+ test "matches action when there are inclusive restrictions on action (symbol)" do
111
+ assert _matches_action?({:only => :index}, :index)
112
+ end
113
+
114
+ test "matches action when there are exclusive restrictions on action (array)" do
115
+ assert _matches_action?({:except => [:update, :create, :delete]}, :index)
116
+ end
117
+
118
+ test "matches action when there are exclusive restrictions on action (symbol)" do
119
+ assert _matches_action?({:except => :update}, :index)
120
+ end
121
+
122
+ test "does not match action when there are inclusive restrictions on action (array)" do
123
+ assert !_matches_action?({:only => [:index, :new, :create]}, :update)
124
+ end
125
+
126
+ test "does not match action when there are inclusive restrictions on action (symbol)" do
127
+ assert !_matches_action?({:only => :index}, :update)
128
+ end
129
+
130
+ test "does not match action when there are exclusive restrictions on action (array)" do
131
+ assert !_matches_action?({:except => [:update, :create, :delete]}, :update)
132
+ end
133
+
134
+ test "does not match action when there are exclusive restrictions on action (symbol)" do
135
+ assert !_matches_action?({:except => :update}, :update)
136
+ end
137
+
138
+ test "accepts a block when it's not there" do
139
+ assert _block_is_successful?(nil)
140
+ end
141
+
142
+ test "accepts a block when it returns true" do
143
+ assert _block_is_successful?(lambda { true })
144
+ end
145
+
146
+ test "refuses a block when it returns false" do
147
+ assert !_block_is_successful?(lambda { false })
148
+ end
149
+
150
+ test "matches scope when there is no scope" do
151
+ assert _matches_scope?(nil, {}, nil)
152
+ end
153
+
154
+ test "matches scope when the object ID matches the ID in the params" do
155
+ assert _matches_scope?(:organization,
156
+ {:organization_id => 12}.with_indifferent_access,
157
+ Resource.new(:organization => Resource.new(:id => 12)))
158
+ end
159
+
160
+ test "does not match scope when the ID in the params is blank" do
161
+ assert !_matches_scope?(:organization,
162
+ {}.with_indifferent_access,
163
+ Resource.new(:organization => Resource.new(:id => 12)))
164
+ end
165
+
166
+ test "does not match scope when the object ID is nil" do
167
+ assert !_matches_scope?(:organization,
168
+ {:organization_id => 12}.with_indifferent_access,
169
+ Resource.new(:organization => Resource.new(:id => nil)))
170
+ end
171
+
172
+ test "does not match scope when both params are blank and the object ID is nil" do
173
+ assert !_matches_scope?(:organization,
174
+ {}.with_indifferent_access,
175
+ Resource.new(:organization => Resource.new(:id => nil)))
176
+ end
177
+
178
+ test "does not match scope when the object ID does not match the ID in the params" do
179
+ assert !_matches_scope?(:organization,
180
+ {:organization_id => 32 }.with_indifferent_access,
181
+ Resource.new(:organization => Resource.new(:id => 65)))
182
+ end
183
+
184
+ test "matches user resource when it doesn't have to run" do
185
+ assert _matches_user_resource?(false, {}, nil)
186
+ end
187
+
188
+ test "matches user resource when it matches the params" do
189
+ assert _matches_user_resource?(true, {:id => 12}.with_indifferent_access, Resource.new(:id => 12))
190
+ end
191
+
192
+ test "does not match user resource when the params are empty" do
193
+ assert !_matches_user_resource?(true, {}.with_indifferent_access, Resource.new(:id => 12))
194
+ end
195
+
196
+ test "does not match user resource when the params are wrong" do
197
+ assert !_matches_user_resource?(true, {:id => 32}.with_indifferent_access, Resource.new(:id => 12))
198
+ end
199
+
200
+ test "does not match user resource when the resource has no ID" do
201
+ assert !_matches_user_resource?(true, {:id => 12}.with_indifferent_access, Resource.new(:id => nil))
202
+ end
203
+
204
+ test "matches authenticated requirement when it doesn't have to run (boolean)" do
205
+ assert _matches_authenticated_requirement?(false, nil)
206
+ end
224
207
 
225
- def assert_action_allowed(h)
226
- h.each do |pair, value|
227
- params = HashWithIndifferentAccess.new(:action => pair.last)
228
- assert_equal value, action_allowed?(params, pair.first), "For #{pair.inspect} => #{value.inspect}"
229
- end
208
+ test "matches authenticated requirement when it doesn't have to run (nil)" do
209
+ assert _matches_authenticated_requirement?(nil, nil)
230
210
  end
231
211
 
232
- def assert_resource_allowed(h)
233
- h.each do |triplet, value|
234
- params = HashWithIndifferentAccess.new(triplet.first)
235
- assert_equal value, resource_allowed?(params, triplet[1], triplet.last ? Resource.new(triplet.last) : nil), "For #{triplet.inspect} => #{value.inspect}"
236
- end
212
+ test "matches authenticated requirement when authenticated is thruthy" do
213
+ assert _matches_authenticated_requirement?(true, Resource.new)
237
214
  end
238
215
 
239
- def assert_block_allowed(h)
240
- h.each do |role, value|
241
- assert_equal value, block_allowed?(role)
242
- end
216
+ test "does not match authenticated requirement when authenticated is not thruthy (boolean)" do
217
+ assert !_matches_authenticated_requirement?(true, false)
243
218
  end
244
219
 
245
- def assert_block_access(h)
246
- h.each do |pair, value|
247
- @authenticated = Resource.new :role => pair.first
248
- @params = {:action => pair.last}
249
- assert_equal value, block_access, "For #{pair.inspect} => #{value.inspect}"
250
- end
220
+ test "does not match authenticated requirement when authenticated is not thruthy (nil)" do
221
+ assert !_matches_authenticated_requirement?(true, nil)
251
222
  end
252
223
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path('../../test_helper', __FILE__)
1
+ require 'test_helper'
2
2
 
3
3
  require 'controllers/application_controller'
4
4
  require 'controllers/users_controller'
@@ -0,0 +1,52 @@
1
+ module MethodsHelpers
2
+ attr_reader :access_allowed_for, :params
3
+
4
+ def logger
5
+ @logger ||= Logger.new('/dev/null')
6
+ end
7
+
8
+ def do_false
9
+ false
10
+ end
11
+
12
+ def do_true
13
+ true
14
+ end
15
+
16
+ def set_rules(rules)
17
+ @access_allowed_for = rules.with_indifferent_access
18
+ end
19
+
20
+ def set_params(params)
21
+ @params = params.with_indifferent_access
22
+ end
23
+
24
+ def assert_action_allowed(h)
25
+ h.each do |(role, action), value|
26
+ params = {:action => action}.with_indifferent_access
27
+ assert_equal(value, action_allowed?(params, role), "Expected #{role} to access #{action} with params #{params.inspect}")
28
+ end
29
+ end
30
+
31
+ def assert_resource_allowed(h)
32
+ h.each do |(params, role, authenticated), value|
33
+ params = params.with_indifferent_access
34
+ authenticated = authenticated ? Resource.new(authenticated) : nil
35
+ assert_equal(value, resource_allowed?(params, role, authenticated), "Expected #{role} #{authenticated} to access #{params.inspect}")
36
+ end
37
+ end
38
+
39
+ def assert_block_allowed(h)
40
+ h.each do |role, value|
41
+ assert_equal value, block_allowed?(role)
42
+ end
43
+ end
44
+
45
+ def assert_block_access(h)
46
+ h.each do |(role, action), expected|
47
+ @authenticated = Resource.new(:role => role)
48
+ @params = {:action => action}.with_indifferent_access
49
+ assert_equal(expected, block_access, "Expected #{role} #{@authenticated} #{expected ? '' : 'NOT '}to access #{action}")
50
+ end
51
+ end
52
+ end
@@ -14,6 +14,10 @@ class Resource
14
14
  @attributes['id'] = value
15
15
  end
16
16
 
17
+ def to_s
18
+ "#<Resource:#{object_id} #{@attributes.inspect}>"
19
+ end
20
+
17
21
  def method_missing(m, v=nil)
18
22
  if m.to_s =~ /(.*)=$/
19
23
  @attributes[$1] = v
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../../shared', __FILE__)
2
+
3
+ module AuthorizationSanTest
4
+ module Initializer
5
+ def self.load_dependencies
6
+ if rails_directory
7
+ $:.unshift(File.join(rails_directory, 'activesupport', 'lib'))
8
+ $:.unshift(File.join(rails_directory, 'activerecord', 'lib'))
9
+ else
10
+ require 'rubygems'
11
+ gem 'rails', '< 3.0'
12
+ end
13
+
14
+ require 'test/unit'
15
+
16
+ require 'active_support'
17
+ require 'active_support/test_case'
18
+ require 'active_record'
19
+ require 'active_record/test_case'
20
+ require 'active_record/base' # this is needed because of dependency hell
21
+ require 'action_controller'
22
+
23
+ $:.unshift File.expand_path('../../lib', __FILE__)
24
+ require File.join(PLUGIN_ROOT, 'rails', 'init')
25
+ end
26
+ end
27
+ end
28
+
29
+ AuthorizationSanTest::Initializer.start
@@ -0,0 +1,29 @@
1
+ require File.expand_path('../../shared', __FILE__)
2
+
3
+ module AuthorizationSanTest
4
+ module Initializer
5
+ def self.load_dependencies
6
+ if rails_directory
7
+ $:.unshift(File.join(rails_directory, 'activesupport', 'lib'))
8
+ $:.unshift(File.join(rails_directory, 'activerecord', 'lib'))
9
+ else
10
+ require 'rubygems'
11
+ gem 'rails', '> 3.0'
12
+ end
13
+
14
+ require 'test/unit'
15
+
16
+ require 'active_support'
17
+ require 'active_support/test_case'
18
+ require 'active_record'
19
+ require 'active_record/test_case'
20
+ require 'active_record/base' # this is needed because of dependency hell
21
+ require 'action_controller'
22
+
23
+ $:.unshift File.expand_path('../../lib', __FILE__)
24
+ require File.join(PLUGIN_ROOT, 'rails', 'init')
25
+ end
26
+ end
27
+ end
28
+
29
+ AuthorizationSanTest::Initializer.start
@@ -0,0 +1,17 @@
1
+ module AuthorizationSanTest
2
+ module Initializer
3
+ VENDOR_RAILS = File.expand_path('../../../../../rails', __FILE__)
4
+ PLUGIN_ROOT = File.expand_path('../../../', __FILE__)
5
+
6
+ def self.rails_directory
7
+ if File.exist?(VENDOR_RAILS)
8
+ VENDOR_RAILS
9
+ end
10
+ end
11
+
12
+ def self.start
13
+ load_dependencies
14
+ ActionController::Routing::Routes.reload rescue nil
15
+ end
16
+ end
17
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: authorization-san
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 15
5
5
  prerelease:
6
6
  segments:
7
- - 1
8
- - 0
9
7
  - 2
10
- version: 1.0.2
8
+ - 0
9
+ - 0
10
+ version: 2.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Manfred Stienstra
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-02-23 00:00:00 +01:00
18
+ date: 2011-03-02 00:00:00 +01:00
19
19
  default_executable:
20
20
  dependencies: []
21
21
 
@@ -34,6 +34,7 @@ files:
34
34
  - lib/authorization.rb
35
35
  - lib/authorization/allow_access.rb
36
36
  - lib/authorization/block_access.rb
37
+ - lib/authorization/deprecated.rb
37
38
  - rails/init.rb
38
39
  - examples/administrations_controller.rb
39
40
  - examples/application.rb
@@ -44,6 +45,7 @@ files:
44
45
  - examples/public_controller.rb
45
46
  - examples/users_controller.rb
46
47
  - test/cases/behaviour_test.rb
48
+ - test/cases/deprecated_test.rb
47
49
  - test/cases/internals_test.rb
48
50
  - test/cases/structural_test.rb
49
51
  - test/controllers/all.rb
@@ -54,8 +56,11 @@ files:
54
56
  - test/controllers/multiple_roles_controller.rb
55
57
  - test/controllers/public_controller.rb
56
58
  - test/controllers/users_controller.rb
59
+ - test/helpers/methods.rb
57
60
  - test/models/resource.rb
58
- - test/test_helper.rb
61
+ - test/test_helper/rails2/test_helper.rb
62
+ - test/test_helper/rails3/test_helper.rb
63
+ - test/test_helper/shared.rb
59
64
  has_rdoc: true
60
65
  homepage: http://fingertips.github.com
61
66
  licenses: []
@@ -100,6 +105,7 @@ test_files:
100
105
  - examples/public_controller.rb
101
106
  - examples/users_controller.rb
102
107
  - test/cases/behaviour_test.rb
108
+ - test/cases/deprecated_test.rb
103
109
  - test/cases/internals_test.rb
104
110
  - test/cases/structural_test.rb
105
111
  - test/controllers/all.rb
@@ -110,5 +116,8 @@ test_files:
110
116
  - test/controllers/multiple_roles_controller.rb
111
117
  - test/controllers/public_controller.rb
112
118
  - test/controllers/users_controller.rb
119
+ - test/helpers/methods.rb
113
120
  - test/models/resource.rb
114
- - test/test_helper.rb
121
+ - test/test_helper/rails2/test_helper.rb
122
+ - test/test_helper/rails3/test_helper.rb
123
+ - test/test_helper/shared.rb
data/test/test_helper.rb DELETED
@@ -1,49 +0,0 @@
1
- module AuthorizationSanTest
2
- module Initializer
3
- VENDOR_RAILS = File.expand_path('../../../../rails', __FILE__)
4
- OTHER_RAILS = File.expand_path('../../../rails', __FILE__)
5
- PLUGIN_ROOT = File.expand_path('../../', __FILE__)
6
-
7
- def self.rails_directory
8
- if File.exist?(VENDOR_RAILS)
9
- VENDOR_RAILS
10
- elsif File.exist?(OTHER_RAILS)
11
- OTHER_RAILS
12
- end
13
- end
14
-
15
- def self.load_dependencies
16
- $stdout.write('Loading Rails from ')
17
- if rails_directory
18
- puts rails_directory
19
- $:.unshift(File.join(rails_directory, 'activesupport', 'lib'))
20
- $:.unshift(File.join(rails_directory, 'activerecord', 'lib'))
21
- else
22
- puts 'rubygems'
23
- begin
24
- require 'rubygems'
25
- gem 'rails', '< 3.0'
26
- rescue LoadError
27
- end
28
- end
29
-
30
- require 'test/unit'
31
- require 'active_support'
32
- require 'active_support/test_case'
33
- require 'action_controller'
34
- require 'action_controller/test_process'
35
-
36
- require File.join(PLUGIN_ROOT, 'rails', 'init')
37
-
38
- $:.unshift(File.join(PLUGIN_ROOT, 'lib'))
39
- $:.unshift(File.join(PLUGIN_ROOT, 'test'))
40
- end
41
-
42
- def self.start
43
- load_dependencies
44
- ActionController::Routing::Routes.reload rescue nil
45
- end
46
- end
47
- end
48
-
49
- AuthorizationSanTest::Initializer.start