ae_declarative_authorization 0.7.1 → 0.8.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.
Files changed (56) hide show
  1. checksums.yaml +5 -5
  2. data/Appraisals +31 -21
  3. data/CHANGELOG +189 -189
  4. data/Gemfile +7 -7
  5. data/Gemfile.lock +68 -60
  6. data/LICENSE.txt +20 -20
  7. data/README.md +620 -620
  8. data/README.rdoc +597 -597
  9. data/Rakefile +35 -33
  10. data/authorization_rules.dist.rb +20 -20
  11. data/declarative_authorization.gemspec +24 -24
  12. data/gemfiles/rails4252.gemfile +10 -10
  13. data/gemfiles/rails4252.gemfile.lock +126 -0
  14. data/gemfiles/rails4271.gemfile +10 -10
  15. data/gemfiles/rails4271.gemfile.lock +126 -0
  16. data/gemfiles/rails507.gemfile +11 -11
  17. data/gemfiles/rails507.gemfile.lock +136 -0
  18. data/gemfiles/rails516.gemfile +11 -0
  19. data/gemfiles/rails516.gemfile.lock +136 -0
  20. data/gemfiles/rails521.gemfile +11 -0
  21. data/gemfiles/rails521.gemfile.lock +144 -0
  22. data/init.rb +5 -5
  23. data/lib/declarative_authorization.rb +18 -18
  24. data/lib/declarative_authorization/authorization.rb +821 -821
  25. data/lib/declarative_authorization/helper.rb +78 -78
  26. data/lib/declarative_authorization/in_controller.rb +713 -713
  27. data/lib/declarative_authorization/in_model.rb +156 -156
  28. data/lib/declarative_authorization/maintenance.rb +215 -215
  29. data/lib/declarative_authorization/obligation_scope.rb +348 -345
  30. data/lib/declarative_authorization/railsengine.rb +5 -5
  31. data/lib/declarative_authorization/reader.rb +549 -549
  32. data/lib/declarative_authorization/test/helpers.rb +261 -261
  33. data/lib/declarative_authorization/version.rb +3 -3
  34. data/lib/generators/authorization/install/install_generator.rb +77 -77
  35. data/lib/generators/authorization/rules/rules_generator.rb +13 -13
  36. data/lib/generators/authorization/rules/templates/authorization_rules.rb +27 -27
  37. data/lib/tasks/authorization_tasks.rake +89 -89
  38. data/log/test.log +15246 -0
  39. data/pkg/ae_declarative_authorization-0.7.1.gem +0 -0
  40. data/pkg/ae_declarative_authorization-0.8.0.gem +0 -0
  41. data/test/authorization_test.rb +1121 -1121
  42. data/test/controller_filter_resource_access_test.rb +573 -573
  43. data/test/controller_test.rb +478 -478
  44. data/test/database.yml +3 -3
  45. data/test/dsl_reader_test.rb +178 -178
  46. data/test/functional/filter_access_to_with_id_in_scope_test.rb +88 -88
  47. data/test/functional/no_filter_access_to_test.rb +79 -79
  48. data/test/functional/params_block_arity_test.rb +39 -39
  49. data/test/helper_test.rb +248 -248
  50. data/test/maintenance_test.rb +46 -46
  51. data/test/model_test.rb +1840 -1840
  52. data/test/profiles/access_checking +20 -0
  53. data/test/schema.sql +60 -60
  54. data/test/test_helper.rb +174 -174
  55. data/test/test_support/minitest_compatibility.rb +26 -26
  56. metadata +17 -5
@@ -1,156 +1,156 @@
1
- # Authorization::AuthorizationInModel
2
- require File.dirname(__FILE__) + '/authorization.rb'
3
- require File.dirname(__FILE__) + '/obligation_scope.rb'
4
-
5
- module Authorization
6
-
7
- module AuthorizationInModel
8
-
9
- # If the user meets the given privilege, permitted_to? returns true
10
- # and yields to the optional block.
11
- def permitted_to?(privilege, options = {})
12
- options = {
13
- :user => Authorization.current_user,
14
- :object => self
15
- }.merge(options)
16
- Authorization::Engine.instance.permit?(privilege, { :user => options[:user], :object => options[:object]}) do
17
- yield if block_given?
18
- end
19
- end
20
-
21
- # Works similar to the permitted_to? method, but doesn't accept a block
22
- # and throws the authorization exceptions, just like Engine#permit!
23
- def permitted_to!(privilege, options = {})
24
- options = {
25
- :user => Authorization.current_user,
26
- :object => self
27
- }.merge(options)
28
- Authorization::Engine.instance.permit!(privilege, { :user => options[:user], :object => options[:object] }) do
29
- yield if block_given?
30
- end
31
- end
32
-
33
- def self.included(base) # :nodoc:
34
- base.module_eval do
35
- # Builds and returns a scope with joins and conditions satisfying all obligations.
36
- def self.obligation_scope_for( privileges, options = {})
37
- options = {
38
- :user => Authorization.current_user,
39
- :context => nil,
40
- :model => self,
41
- :engine => nil,
42
- }.merge(options)
43
- engine = options[:engine] || Authorization::Engine.instance
44
-
45
- obligation_scope = ObligationScope.new( options[:model], {} )
46
- engine.obligations( privileges, :user => options[:user], :context => options[:context] ).each do |obligation|
47
- obligation_scope.parse!( obligation )
48
- end
49
-
50
- obligation_scope.scope
51
- end
52
-
53
- # Named scope for limiting query results according to the authorization
54
- # of the current user. If no privilege is given, :+read+ is assumed.
55
- #
56
- # User.with_permissions_to
57
- # User.with_permissions_to(:update)
58
- # User.with_permissions_to(:update, :context => :users)
59
- #
60
- # As in the case of other named scopes, this one may be chained:
61
- # User.with_permission_to.find(:all, :conditions...)
62
- #
63
- # Options
64
- # [:+context+]
65
- # Context for the privilege to be evaluated in; defaults to the
66
- # model's table name.
67
- # [:+user+]
68
- # User to be used for gathering obligations; defaults to the
69
- # current user.
70
- #
71
- def self.with_permissions_to(*args)
72
- options = args.last.is_a?(Hash) ? args.pop : {}
73
- privilege = (args[0] || :read).to_sym
74
- privileges = [privilege]
75
- parent_scope = where(nil)
76
- context =
77
- if options[:context]
78
- options[:context]
79
- elsif parent_scope.klass.respond_to?(:decl_auth_context)
80
- parent_scope.klass.decl_auth_context
81
- else
82
- parent_scope.klass.name.tableize.to_sym
83
- end
84
-
85
- user = options[:user] || Authorization.current_user
86
-
87
- engine = options[:engine] || Authorization::Engine.instance
88
- engine.permit!(privileges,
89
- :user => user,
90
- :skip_attribute_test => true,
91
- :context => context)
92
-
93
- obligation_scope_for(privileges,
94
- :user => user,
95
- :context => context,
96
- :engine => engine,
97
- :model => parent_scope.klass)
98
- end
99
-
100
- # Activates model security for the current model. Then, CRUD operations
101
- # are checked against the authorization of the current user. The
102
- # privileges are :+create+, :+read+, :+update+ and :+delete+ in the
103
- # context of the model. By default, :+read+ is not checked because of
104
- # performance impacts, especially with large result sets.
105
- #
106
- # class User < ActiveRecord::Base
107
- # using_access_control
108
- # end
109
- #
110
- # If an operation is not permitted, a Authorization::AuthorizationError
111
- # is raised.
112
- #
113
- # To activate model security on all models, call using_access_control
114
- # on ActiveRecord::Base
115
- # ActiveRecord::Base.using_access_control
116
- #
117
- # Available options
118
- # [:+context+] Specify context different from the models table name.
119
- # [:+include_read+] Also check for :+read+ privilege after find.
120
- #
121
- def self.using_access_control(options = {})
122
- options = {
123
- :context => nil,
124
- :include_read => false
125
- }.merge(options)
126
-
127
- class_eval do
128
- [:create, :update, [:destroy, :delete]].each do |action, privilege|
129
- send(:"before_#{action}") do |object|
130
- Authorization::Engine.instance.permit!(privilege || action,
131
- :object => object, :context => options[:context])
132
- end
133
- end
134
-
135
- if options[:include_read]
136
- # after_find is only called if after_find is implemented
137
- after_find do |object|
138
- Authorization::Engine.instance.permit!(:read, :object => object,
139
- :context => options[:context])
140
- end
141
- end
142
-
143
- def self.using_access_control?
144
- true
145
- end
146
- end
147
- end
148
-
149
- # Returns true if the model is using model security.
150
- def self.using_access_control?
151
- false
152
- end
153
- end
154
- end
155
- end
156
- end
1
+ # Authorization::AuthorizationInModel
2
+ require File.dirname(__FILE__) + '/authorization.rb'
3
+ require File.dirname(__FILE__) + '/obligation_scope.rb'
4
+
5
+ module Authorization
6
+
7
+ module AuthorizationInModel
8
+
9
+ # If the user meets the given privilege, permitted_to? returns true
10
+ # and yields to the optional block.
11
+ def permitted_to?(privilege, options = {})
12
+ options = {
13
+ :user => Authorization.current_user,
14
+ :object => self
15
+ }.merge(options)
16
+ Authorization::Engine.instance.permit?(privilege, { :user => options[:user], :object => options[:object]}) do
17
+ yield if block_given?
18
+ end
19
+ end
20
+
21
+ # Works similar to the permitted_to? method, but doesn't accept a block
22
+ # and throws the authorization exceptions, just like Engine#permit!
23
+ def permitted_to!(privilege, options = {})
24
+ options = {
25
+ :user => Authorization.current_user,
26
+ :object => self
27
+ }.merge(options)
28
+ Authorization::Engine.instance.permit!(privilege, { :user => options[:user], :object => options[:object] }) do
29
+ yield if block_given?
30
+ end
31
+ end
32
+
33
+ def self.included(base) # :nodoc:
34
+ base.module_eval do
35
+ # Builds and returns a scope with joins and conditions satisfying all obligations.
36
+ def self.obligation_scope_for( privileges, options = {})
37
+ options = {
38
+ :user => Authorization.current_user,
39
+ :context => nil,
40
+ :model => self,
41
+ :engine => nil,
42
+ }.merge(options)
43
+ engine = options[:engine] || Authorization::Engine.instance
44
+
45
+ obligation_scope = ObligationScope.new( options[:model], {} )
46
+ engine.obligations( privileges, :user => options[:user], :context => options[:context] ).each do |obligation|
47
+ obligation_scope.parse!( obligation )
48
+ end
49
+
50
+ obligation_scope.scope
51
+ end
52
+
53
+ # Named scope for limiting query results according to the authorization
54
+ # of the current user. If no privilege is given, :+read+ is assumed.
55
+ #
56
+ # User.with_permissions_to
57
+ # User.with_permissions_to(:update)
58
+ # User.with_permissions_to(:update, :context => :users)
59
+ #
60
+ # As in the case of other named scopes, this one may be chained:
61
+ # User.with_permission_to.find(:all, :conditions...)
62
+ #
63
+ # Options
64
+ # [:+context+]
65
+ # Context for the privilege to be evaluated in; defaults to the
66
+ # model's table name.
67
+ # [:+user+]
68
+ # User to be used for gathering obligations; defaults to the
69
+ # current user.
70
+ #
71
+ def self.with_permissions_to(*args)
72
+ options = args.last.is_a?(Hash) ? args.pop : {}
73
+ privilege = (args[0] || :read).to_sym
74
+ privileges = [privilege]
75
+ parent_scope = where(nil)
76
+ context =
77
+ if options[:context]
78
+ options[:context]
79
+ elsif parent_scope.klass.respond_to?(:decl_auth_context)
80
+ parent_scope.klass.decl_auth_context
81
+ else
82
+ parent_scope.klass.name.tableize.to_sym
83
+ end
84
+
85
+ user = options[:user] || Authorization.current_user
86
+
87
+ engine = options[:engine] || Authorization::Engine.instance
88
+ engine.permit!(privileges,
89
+ :user => user,
90
+ :skip_attribute_test => true,
91
+ :context => context)
92
+
93
+ obligation_scope_for(privileges,
94
+ :user => user,
95
+ :context => context,
96
+ :engine => engine,
97
+ :model => parent_scope.klass)
98
+ end
99
+
100
+ # Activates model security for the current model. Then, CRUD operations
101
+ # are checked against the authorization of the current user. The
102
+ # privileges are :+create+, :+read+, :+update+ and :+delete+ in the
103
+ # context of the model. By default, :+read+ is not checked because of
104
+ # performance impacts, especially with large result sets.
105
+ #
106
+ # class User < ActiveRecord::Base
107
+ # using_access_control
108
+ # end
109
+ #
110
+ # If an operation is not permitted, a Authorization::AuthorizationError
111
+ # is raised.
112
+ #
113
+ # To activate model security on all models, call using_access_control
114
+ # on ActiveRecord::Base
115
+ # ActiveRecord::Base.using_access_control
116
+ #
117
+ # Available options
118
+ # [:+context+] Specify context different from the models table name.
119
+ # [:+include_read+] Also check for :+read+ privilege after find.
120
+ #
121
+ def self.using_access_control(options = {})
122
+ options = {
123
+ :context => nil,
124
+ :include_read => false
125
+ }.merge(options)
126
+
127
+ class_eval do
128
+ [:create, :update, [:destroy, :delete]].each do |action, privilege|
129
+ send(:"before_#{action}") do |object|
130
+ Authorization::Engine.instance.permit!(privilege || action,
131
+ :object => object, :context => options[:context])
132
+ end
133
+ end
134
+
135
+ if options[:include_read]
136
+ # after_find is only called if after_find is implemented
137
+ after_find do |object|
138
+ Authorization::Engine.instance.permit!(:read, :object => object,
139
+ :context => options[:context])
140
+ end
141
+ end
142
+
143
+ def self.using_access_control?
144
+ true
145
+ end
146
+ end
147
+ end
148
+
149
+ # Returns true if the model is using model security.
150
+ def self.using_access_control?
151
+ false
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
@@ -1,215 +1,215 @@
1
- # Authorization::Maintenance
2
- require File.dirname(__FILE__) + '/authorization.rb'
3
-
4
- module Authorization
5
- # Provides a few maintenance methods for modifying data without enforcing
6
- # authorization.
7
- module Maintenance
8
- # Disables access control for the given block. Appropriate for
9
- # maintenance operation at the Rails console or in test case setup.
10
- #
11
- # For use in the Rails console:
12
- # require "vendor/plugins/declarative_authorization/lib/maintenance"
13
- # include Authorization::Maintenance
14
- #
15
- # without_access_control do
16
- # SomeModel.find(:first).save
17
- # end
18
- def without_access_control
19
- Authorization::Maintenance.without_access_control() do
20
- yield if block_given?
21
- end
22
- end
23
-
24
- # A class method variant of without_access_control. Thus, one can call
25
- # Authorization::Maintenance::without_access_control do
26
- # ...
27
- # end
28
- def self.without_access_control
29
- previous_state = Authorization.ignore_access_control
30
- begin
31
- Authorization.ignore_access_control(true)
32
- yield
33
- ensure
34
- Authorization.ignore_access_control(previous_state)
35
- end
36
- end
37
-
38
- # Sets the current user for the declarative authorization plugin to the
39
- # given one for the execution of the supplied block. Suitable for tests
40
- # on certain users.
41
- def with_user(user)
42
- Authorization::Maintenance.with_user(user) do
43
- yield if block_given?
44
- end
45
- end
46
-
47
- def self.with_user(user)
48
- prev_user = Authorization.current_user
49
- Authorization.current_user = user
50
- yield
51
- ensure
52
- Authorization.current_user = prev_user
53
- end
54
-
55
- # Module for grouping usage-related helper methods
56
- module Usage
57
- # Delivers a hash of {ControllerClass => usage_info_hash},
58
- # where usage_info_hash has the form of
59
- def self.usages_by_controller
60
- # load each application controller
61
- begin
62
- Dir.glob(File.join(::Rails.root, 'app', 'controllers', '**', '*_controller\.rb')) do |entry|
63
- require entry
64
- end
65
- rescue Errno::ENOENT
66
- end
67
- controllers = ObjectSpace.each_object(Class).select do |obj|
68
- obj.ancestors.include?(ActionController::Base) &&
69
- obj != ActionController::Base &&
70
- (!obj.name || obj.name.demodulize != 'ApplicationController')
71
- end
72
-
73
- controllers.inject({}) do |memo, controller|
74
- catchall_permissions = []
75
- permission_by_action = {}
76
- controller.all_filter_access_permissions.each do |controller_permissions|
77
- catchall_permissions << controller_permissions if controller_permissions.actions.include?(:all)
78
- controller_permissions.actions.reject {|action| action == :all}.each do |action|
79
- permission_by_action[action] = controller_permissions
80
- end
81
- end
82
- actions = controller.public_instance_methods(false) - controller.private_methods
83
- memo[controller] = actions.inject({}) do |actions_memo, action|
84
- action_sym = action.to_sym
85
- actions_memo[action_sym] =
86
- if permission_by_action[action_sym]
87
- {
88
- :privilege => permission_by_action[action_sym].privilege,
89
- :context => permission_by_action[action_sym].context,
90
- :controller_permissions => [permission_by_action[action_sym]]
91
- }
92
- elsif !catchall_permissions.empty?
93
- {
94
- :privilege => catchall_permissions[0].privilege,
95
- :context => catchall_permissions[0].context,
96
- :controller_permissions => catchall_permissions
97
- }
98
- else
99
- {}
100
- end
101
- actions_memo
102
- end
103
- memo
104
- end
105
- end
106
- end
107
- end
108
-
109
- # TestHelper provides assert methods and controller request methods which
110
- # take authorization into account and set the current user to a specific
111
- # one.
112
- #
113
- # Defines get_with, post_with, get_by_xhr_with etc. for methods
114
- # get, post, put, delete each with the signature
115
- # get_with(user, action, params = {}, session = {}, flash = {})
116
- #
117
- # Use it by including it in your TestHelper:
118
- # require File.expand_path(File.dirname(__FILE__) +
119
- # "/../vendor/plugins/declarative_authorization/lib/maintenance")
120
- # class Test::Unit::TestCase
121
- # include Authorization::TestHelper
122
- # ...
123
- #
124
- # def admin
125
- # # create admin user
126
- # end
127
- # end
128
- #
129
- # class SomeControllerTest < ActionController::TestCase
130
- # def test_should_get_index
131
- # ...
132
- # get_with admin, :index, :param_1 => "param value"
133
- # ...
134
- # end
135
- # end
136
- #
137
- # Note: get_with etc. do two things to set the user for the request:
138
- # Authorization.current_user is set and session[:user], session[:user_id]
139
- # are set appropriately. If you determine the current user in a different
140
- # way, these methods might not work for you.
141
- module TestHelper
142
- include Authorization::Maintenance
143
-
144
- # Analogue to the Ruby's assert_raise method, only executing the block
145
- # in the context of the given user.
146
- def assert_raise_with_user(user, *args)
147
- assert_raise(*args) do
148
- with_user(user) do
149
- yield if block_given?
150
- end
151
- end
152
- end
153
-
154
- # Test helper to test authorization rules.
155
- # with_user a_normal_user do
156
- # should_not_be_allowed_to :update, :conferences
157
- # should_not_be_allowed_to :read, an_unpublished_conference
158
- # should_be_allowed_to :read, a_published_conference
159
- # end
160
- #
161
- # If the objects class name does not match the controller name, you can set the object and context manually
162
- # should_be_allowed_to :create, :object => car, :context => :vehicles
163
- #
164
- # If you use specify the object and context manually, you can also specify the user manually, skipping the with_user block:
165
- # should_be_allowed_to :create, :object => car, :context => :vehicles, :user => a_normal_user
166
- def should_be_allowed_to(privilege, *args)
167
- options = {}
168
- if(args.first.class == Hash)
169
- options = args.extract_options!
170
- else
171
- options[args[0].is_a?(Symbol) ? :context : :object] = args[0]
172
- end
173
- assert_nothing_raised do
174
- Authorization::Engine.instance.permit!(privilege, options)
175
- end
176
- end
177
-
178
- # See should_be_allowed_to
179
- def should_not_be_allowed_to(privilege, *args)
180
- options = {}
181
- if(args.first.class == Hash)
182
- options = args.extract_options!
183
- else
184
- options[args[0].is_a?(Symbol) ? :context : :object] = args[0]
185
- end
186
- assert !Authorization::Engine.instance.permit?(privilege, options)
187
- end
188
-
189
- def request_with(user, method, xhr, action, params = {},
190
- session = {}, flash = {})
191
- session = session.merge({:user => user, :user_id => user && user.id})
192
- with_user(user) do
193
- if xhr
194
- xhr method, action, params, session, flash
195
- else
196
- send method, action, params, session, flash
197
- end
198
- end
199
- end
200
-
201
- def self.included(base)
202
- [:get, :post, :put, :delete].each do |method|
203
- base.class_eval <<-EOV, __FILE__, __LINE__
204
- def #{method}_with(user, *args)
205
- request_with(user, #{method.inspect}, false, *args)
206
- end
207
-
208
- def #{method}_by_xhr_with(user, *args)
209
- request_with(user, #{method.inspect}, true, *args)
210
- end
211
- EOV
212
- end
213
- end
214
- end
215
- end
1
+ # Authorization::Maintenance
2
+ require File.dirname(__FILE__) + '/authorization.rb'
3
+
4
+ module Authorization
5
+ # Provides a few maintenance methods for modifying data without enforcing
6
+ # authorization.
7
+ module Maintenance
8
+ # Disables access control for the given block. Appropriate for
9
+ # maintenance operation at the Rails console or in test case setup.
10
+ #
11
+ # For use in the Rails console:
12
+ # require "vendor/plugins/declarative_authorization/lib/maintenance"
13
+ # include Authorization::Maintenance
14
+ #
15
+ # without_access_control do
16
+ # SomeModel.find(:first).save
17
+ # end
18
+ def without_access_control
19
+ Authorization::Maintenance.without_access_control() do
20
+ yield if block_given?
21
+ end
22
+ end
23
+
24
+ # A class method variant of without_access_control. Thus, one can call
25
+ # Authorization::Maintenance::without_access_control do
26
+ # ...
27
+ # end
28
+ def self.without_access_control
29
+ previous_state = Authorization.ignore_access_control
30
+ begin
31
+ Authorization.ignore_access_control(true)
32
+ yield
33
+ ensure
34
+ Authorization.ignore_access_control(previous_state)
35
+ end
36
+ end
37
+
38
+ # Sets the current user for the declarative authorization plugin to the
39
+ # given one for the execution of the supplied block. Suitable for tests
40
+ # on certain users.
41
+ def with_user(user)
42
+ Authorization::Maintenance.with_user(user) do
43
+ yield if block_given?
44
+ end
45
+ end
46
+
47
+ def self.with_user(user)
48
+ prev_user = Authorization.current_user
49
+ Authorization.current_user = user
50
+ yield
51
+ ensure
52
+ Authorization.current_user = prev_user
53
+ end
54
+
55
+ # Module for grouping usage-related helper methods
56
+ module Usage
57
+ # Delivers a hash of {ControllerClass => usage_info_hash},
58
+ # where usage_info_hash has the form of
59
+ def self.usages_by_controller
60
+ # load each application controller
61
+ begin
62
+ Dir.glob(File.join(::Rails.root, 'app', 'controllers', '**', '*_controller\.rb')) do |entry|
63
+ require entry
64
+ end
65
+ rescue Errno::ENOENT
66
+ end
67
+ controllers = ObjectSpace.each_object(Class).select do |obj|
68
+ obj.ancestors.include?(ActionController::Base) &&
69
+ obj != ActionController::Base &&
70
+ (!obj.name || obj.name.demodulize != 'ApplicationController')
71
+ end
72
+
73
+ controllers.inject({}) do |memo, controller|
74
+ catchall_permissions = []
75
+ permission_by_action = {}
76
+ controller.all_filter_access_permissions.each do |controller_permissions|
77
+ catchall_permissions << controller_permissions if controller_permissions.actions.include?(:all)
78
+ controller_permissions.actions.reject {|action| action == :all}.each do |action|
79
+ permission_by_action[action] = controller_permissions
80
+ end
81
+ end
82
+ actions = controller.public_instance_methods(false) - controller.private_methods
83
+ memo[controller] = actions.inject({}) do |actions_memo, action|
84
+ action_sym = action.to_sym
85
+ actions_memo[action_sym] =
86
+ if permission_by_action[action_sym]
87
+ {
88
+ :privilege => permission_by_action[action_sym].privilege,
89
+ :context => permission_by_action[action_sym].context,
90
+ :controller_permissions => [permission_by_action[action_sym]]
91
+ }
92
+ elsif !catchall_permissions.empty?
93
+ {
94
+ :privilege => catchall_permissions[0].privilege,
95
+ :context => catchall_permissions[0].context,
96
+ :controller_permissions => catchall_permissions
97
+ }
98
+ else
99
+ {}
100
+ end
101
+ actions_memo
102
+ end
103
+ memo
104
+ end
105
+ end
106
+ end
107
+ end
108
+
109
+ # TestHelper provides assert methods and controller request methods which
110
+ # take authorization into account and set the current user to a specific
111
+ # one.
112
+ #
113
+ # Defines get_with, post_with, get_by_xhr_with etc. for methods
114
+ # get, post, put, delete each with the signature
115
+ # get_with(user, action, params = {}, session = {}, flash = {})
116
+ #
117
+ # Use it by including it in your TestHelper:
118
+ # require File.expand_path(File.dirname(__FILE__) +
119
+ # "/../vendor/plugins/declarative_authorization/lib/maintenance")
120
+ # class Test::Unit::TestCase
121
+ # include Authorization::TestHelper
122
+ # ...
123
+ #
124
+ # def admin
125
+ # # create admin user
126
+ # end
127
+ # end
128
+ #
129
+ # class SomeControllerTest < ActionController::TestCase
130
+ # def test_should_get_index
131
+ # ...
132
+ # get_with admin, :index, :param_1 => "param value"
133
+ # ...
134
+ # end
135
+ # end
136
+ #
137
+ # Note: get_with etc. do two things to set the user for the request:
138
+ # Authorization.current_user is set and session[:user], session[:user_id]
139
+ # are set appropriately. If you determine the current user in a different
140
+ # way, these methods might not work for you.
141
+ module TestHelper
142
+ include Authorization::Maintenance
143
+
144
+ # Analogue to the Ruby's assert_raise method, only executing the block
145
+ # in the context of the given user.
146
+ def assert_raise_with_user(user, *args)
147
+ assert_raise(*args) do
148
+ with_user(user) do
149
+ yield if block_given?
150
+ end
151
+ end
152
+ end
153
+
154
+ # Test helper to test authorization rules.
155
+ # with_user a_normal_user do
156
+ # should_not_be_allowed_to :update, :conferences
157
+ # should_not_be_allowed_to :read, an_unpublished_conference
158
+ # should_be_allowed_to :read, a_published_conference
159
+ # end
160
+ #
161
+ # If the objects class name does not match the controller name, you can set the object and context manually
162
+ # should_be_allowed_to :create, :object => car, :context => :vehicles
163
+ #
164
+ # If you use specify the object and context manually, you can also specify the user manually, skipping the with_user block:
165
+ # should_be_allowed_to :create, :object => car, :context => :vehicles, :user => a_normal_user
166
+ def should_be_allowed_to(privilege, *args)
167
+ options = {}
168
+ if(args.first.class == Hash)
169
+ options = args.extract_options!
170
+ else
171
+ options[args[0].is_a?(Symbol) ? :context : :object] = args[0]
172
+ end
173
+ assert_nothing_raised do
174
+ Authorization::Engine.instance.permit!(privilege, options)
175
+ end
176
+ end
177
+
178
+ # See should_be_allowed_to
179
+ def should_not_be_allowed_to(privilege, *args)
180
+ options = {}
181
+ if(args.first.class == Hash)
182
+ options = args.extract_options!
183
+ else
184
+ options[args[0].is_a?(Symbol) ? :context : :object] = args[0]
185
+ end
186
+ assert !Authorization::Engine.instance.permit?(privilege, options)
187
+ end
188
+
189
+ def request_with(user, method, xhr, action, params = {},
190
+ session = {}, flash = {})
191
+ session = session.merge({:user => user, :user_id => user && user.id})
192
+ with_user(user) do
193
+ if xhr
194
+ xhr method, action, params, session, flash
195
+ else
196
+ send method, action, params, session, flash
197
+ end
198
+ end
199
+ end
200
+
201
+ def self.included(base)
202
+ [:get, :post, :put, :delete].each do |method|
203
+ base.class_eval <<-EOV, __FILE__, __LINE__
204
+ def #{method}_with(user, *args)
205
+ request_with(user, #{method.inspect}, false, *args)
206
+ end
207
+
208
+ def #{method}_by_xhr_with(user, *args)
209
+ request_with(user, #{method.inspect}, true, *args)
210
+ end
211
+ EOV
212
+ end
213
+ end
214
+ end
215
+ end