authorization-san 1.0.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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