careacademy-acl9 3.3.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 (138) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +24 -0
  3. data/.ruby-version +1 -0
  4. data/.travis.yml +26 -0
  5. data/Appraisals +23 -0
  6. data/CHANGELOG.md +122 -0
  7. data/CONTRIBUTING.md +62 -0
  8. data/Gemfile +7 -0
  9. data/Gemfile.lock +167 -0
  10. data/LICENSE +9 -0
  11. data/MIT-LICENSE +20 -0
  12. data/README.md +326 -0
  13. data/Rakefile +20 -0
  14. data/TODO +42 -0
  15. data/acl9.gemspec +27 -0
  16. data/bin/appraisal +16 -0
  17. data/bin/bundler +16 -0
  18. data/bin/cc-tddium-post-worker +16 -0
  19. data/bin/erubis +16 -0
  20. data/bin/rackup +16 -0
  21. data/bin/rails +16 -0
  22. data/bin/rake +16 -0
  23. data/bin/sprockets +16 -0
  24. data/bin/tapout +16 -0
  25. data/bin/thor +16 -0
  26. data/bin/tilt +16 -0
  27. data/bin/yard +16 -0
  28. data/bin/yardoc +16 -0
  29. data/bin/yri +16 -0
  30. data/gemfiles/.bundle/config +2 -0
  31. data/gemfiles/rails_5.0.gemfile +10 -0
  32. data/gemfiles/rails_5.1.gemfile +10 -0
  33. data/gemfiles/rails_5.2.gemfile +9 -0
  34. data/gemfiles/rails_6.0.gemfile +9 -0
  35. data/gemfiles/rails_6.1.gemfile +9 -0
  36. data/gemfiles/rails_7.0.gemfile +9 -0
  37. data/lib/acl9/controller_extensions/dsl_base.rb +212 -0
  38. data/lib/acl9/controller_extensions/generators.rb +166 -0
  39. data/lib/acl9/controller_extensions.rb +85 -0
  40. data/lib/acl9/helpers.rb +49 -0
  41. data/lib/acl9/model_extensions/for_object.rb +74 -0
  42. data/lib/acl9/model_extensions/for_subject.rb +232 -0
  43. data/lib/acl9/model_extensions.rb +136 -0
  44. data/lib/acl9/prepositions.rb +18 -0
  45. data/lib/acl9/version.rb +3 -0
  46. data/lib/acl9.rb +78 -0
  47. data/lib/generators/acl9/setup/USAGE +35 -0
  48. data/lib/generators/acl9/setup/setup_generator.rb +122 -0
  49. data/lib/generators/acl9/setup/templates/create_role_tables.rb +31 -0
  50. data/lib/generators/acl9/setup/templates/role.rb +3 -0
  51. data/test/config_test.rb +55 -0
  52. data/test/controller_extensions/actions_test.rb +199 -0
  53. data/test/controller_extensions/anon_test.rb +39 -0
  54. data/test/controller_extensions/base.rb +96 -0
  55. data/test/controller_extensions/basics_test.rb +44 -0
  56. data/test/controller_extensions/conditions_test.rb +48 -0
  57. data/test/controller_extensions/method_test.rb +70 -0
  58. data/test/controller_extensions/multi_match_test.rb +142 -0
  59. data/test/controller_extensions/multiple_role_arguments_test.rb +136 -0
  60. data/test/controller_extensions/prepositions_test.rb +108 -0
  61. data/test/controller_extensions/pseudo_role_test.rb +26 -0
  62. data/test/controller_extensions/role_test.rb +75 -0
  63. data/test/controllers/acl_action_override_test.rb +24 -0
  64. data/test/controllers/acl_arguments_test.rb +5 -0
  65. data/test/controllers/acl_block_test.rb +5 -0
  66. data/test/controllers/acl_boolean_method_test.rb +5 -0
  67. data/test/controllers/acl_helper_method_test.rb +29 -0
  68. data/test/controllers/acl_ivars_test.rb +15 -0
  69. data/test/controllers/acl_method2_test.rb +6 -0
  70. data/test/controllers/acl_method_test.rb +6 -0
  71. data/test/controllers/acl_object_hash_test.rb +18 -0
  72. data/test/controllers/acl_query_method_named_test.rb +9 -0
  73. data/test/controllers/acl_query_method_test.rb +9 -0
  74. data/test/controllers/acl_query_method_with_lambda_test.rb +9 -0
  75. data/test/controllers/acl_query_mixin.rb +54 -0
  76. data/test/controllers/acl_subject_method_test.rb +15 -0
  77. data/test/controllers/arguments_checking_test.rb +43 -0
  78. data/test/dummy/app/assets/config/manifest.js +0 -0
  79. data/test/dummy/app/controllers/acl_action_override.rb +15 -0
  80. data/test/dummy/app/controllers/acl_arguments.rb +10 -0
  81. data/test/dummy/app/controllers/acl_block.rb +6 -0
  82. data/test/dummy/app/controllers/acl_boolean_method.rb +23 -0
  83. data/test/dummy/app/controllers/acl_helper_method.rb +11 -0
  84. data/test/dummy/app/controllers/acl_ivars.rb +17 -0
  85. data/test/dummy/app/controllers/acl_method.rb +6 -0
  86. data/test/dummy/app/controllers/acl_method2.rb +6 -0
  87. data/test/dummy/app/controllers/acl_objects_hash.rb +10 -0
  88. data/test/dummy/app/controllers/acl_query_method.rb +9 -0
  89. data/test/dummy/app/controllers/acl_query_method_named.rb +15 -0
  90. data/test/dummy/app/controllers/acl_query_method_with_lambda.rb +9 -0
  91. data/test/dummy/app/controllers/acl_subject_method.rb +16 -0
  92. data/test/dummy/app/controllers/application_controller.rb +13 -0
  93. data/test/dummy/app/controllers/empty_controller.rb +5 -0
  94. data/test/dummy/app/helpers/application_helper.rb +2 -0
  95. data/test/dummy/app/helpers/some_helper.rb +8 -0
  96. data/test/dummy/app/models/.keep +0 -0
  97. data/test/dummy/app/models/access.rb +3 -0
  98. data/test/dummy/app/models/account.rb +3 -0
  99. data/test/dummy/app/models/bar.rb +3 -0
  100. data/test/dummy/app/models/concerns/.keep +0 -0
  101. data/test/dummy/app/models/foo.rb +3 -0
  102. data/test/dummy/app/models/foo_bar.rb +3 -0
  103. data/test/dummy/app/models/other/foo.rb +5 -0
  104. data/test/dummy/app/models/other/role.rb +5 -0
  105. data/test/dummy/app/models/other/user.rb +5 -0
  106. data/test/dummy/app/models/role.rb +3 -0
  107. data/test/dummy/app/models/string_object_role.rb +3 -0
  108. data/test/dummy/app/models/string_user.rb +3 -0
  109. data/test/dummy/app/models/user.rb +3 -0
  110. data/test/dummy/app/models/uuid.rb +4 -0
  111. data/test/dummy/config/application.rb +23 -0
  112. data/test/dummy/config/boot.rb +4 -0
  113. data/test/dummy/config/database.yml +25 -0
  114. data/test/dummy/config/environment.rb +5 -0
  115. data/test/dummy/config/environments/development.rb +37 -0
  116. data/test/dummy/config/environments/test.rb +40 -0
  117. data/test/dummy/config/initializers/assets.rb +8 -0
  118. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  119. data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
  120. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  121. data/test/dummy/config/initializers/inflections.rb +16 -0
  122. data/test/dummy/config/initializers/mime_types.rb +4 -0
  123. data/test/dummy/config/initializers/secrets.rb +1 -0
  124. data/test/dummy/config/initializers/session_store.rb +3 -0
  125. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  126. data/test/dummy/config/locales/en.yml +23 -0
  127. data/test/dummy/config/routes.rb +14 -0
  128. data/test/dummy/config.ru +4 -0
  129. data/test/dummy/db/migrate/20141117132218_create_tables.rb +149 -0
  130. data/test/helpers/helper_test.rb +89 -0
  131. data/test/models/roles_test.rb +369 -0
  132. data/test/models/roles_with_custom_association_names_test.rb +28 -0
  133. data/test/models/roles_with_custom_class_names_test.rb +28 -0
  134. data/test/models/system_roles_test.rb +22 -0
  135. data/test/models/users_roles_and_subjects_with_namespaced_class_names_test.rb +30 -0
  136. data/test/test_helper.rb +94 -0
  137. data/test/version_test.rb +7 -0
  138. metadata +321 -0
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "byebug"
7
+ gem "rails", "~> 5.2.0"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "byebug"
7
+ gem "rails", "~> 6.0.0"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "byebug"
7
+ gem "rails", "~> 6.1.0"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,9 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "byebug"
7
+ gem "rails", "~> 7.0.4.2"
8
+
9
+ gemspec path: "../"
@@ -0,0 +1,212 @@
1
+ require_relative "../prepositions"
2
+
3
+ module Acl9
4
+ module Dsl
5
+ class Base
6
+ include Prepositions
7
+
8
+ attr_reader :allows, :denys
9
+
10
+ def initialize(*args)
11
+ @default_action = nil
12
+ @allows = []
13
+ @denys = []
14
+ @original_args = args
15
+ @action_clause = nil
16
+ end
17
+
18
+ def acl_block!(&acl_block)
19
+ instance_eval(&acl_block)
20
+ end
21
+
22
+ def default_action
23
+ @default_action.nil? ? :deny : @default_action
24
+ end
25
+
26
+ def allowance_expression
27
+ allowed_expr = @allows.any? ? @allows.map { |clause| "(#{clause})" }.join(' || ') : 'false'
28
+ not_denied_expr = @denys.any? ? @denys.map { |clause| "!(#{clause})" }.join(' && ') : 'true'
29
+
30
+ [allowed_expr, not_denied_expr].
31
+ map { |expr| "(#{expr})" }.
32
+ join(default_action == :deny ? ' && ' : ' || ')
33
+ end
34
+
35
+ alias to_s allowance_expression
36
+
37
+ protected
38
+
39
+ def default(default_action)
40
+ raise ArgumentError, "default can only be called once in access_control block" if @default_action
41
+
42
+ unless [:allow, :deny].include? default_action
43
+ raise ArgumentError, "invalid value for default (can be :allow or :deny)"
44
+ end
45
+
46
+ @default_action = default_action
47
+ end
48
+
49
+ def allow(*args)
50
+ @current_rule = :allow
51
+ _parse_and_add_rule(*args)
52
+ end
53
+
54
+ def deny(*args)
55
+ @current_rule = :deny
56
+ _parse_and_add_rule(*args)
57
+ end
58
+
59
+ def actions(*args, &block)
60
+ raise ArgumentError, "actions should receive at least 1 action as argument" if args.size < 1
61
+
62
+ subsidiary = self.class.new(*@original_args)
63
+
64
+ class <<subsidiary
65
+ def actions(*args)
66
+ raise ArgumentError, "You cannot use actions inside another actions block"
67
+ end
68
+
69
+ def default(*args)
70
+ raise ArgumentError, "You cannot use default inside an actions block"
71
+ end
72
+
73
+ def _set_action_clause(only, except)
74
+ raise ArgumentError, "You cannot use :only (:to) or :except inside actions block" if only || except
75
+ end
76
+ end
77
+
78
+ subsidiary.acl_block!(&block)
79
+ action_check = _action_check_expression(args)
80
+ squash = lambda { |rules| action_check + ' && ' + _either_of(rules) }
81
+
82
+ @allows << squash.call(subsidiary.allows) if subsidiary.allows.size > 0
83
+ @denys << squash.call(subsidiary.denys) if subsidiary.denys.size > 0
84
+ end
85
+
86
+ alias action actions
87
+
88
+ def logged_in; false end
89
+ def anonymous; nil end
90
+ def all; true end
91
+
92
+ alias everyone all
93
+ alias everybody all
94
+ alias anyone all
95
+
96
+ def _permitted_allow_deny_option!(key)
97
+ raise ArgumentError, "#{key} is not a valid option" unless [:to, :only, :except, :if, :unless, *VALID_PREPOSITIONS].include?(key.to_sym)
98
+ end
99
+
100
+ def _retrieve_only options
101
+ only = [ options.delete(:only) ].flatten.compact
102
+ only |= [ options.delete(:to) ].flatten.compact
103
+ only if only.present?
104
+ end
105
+
106
+ def _parse_and_add_rule(*args)
107
+ options = args.extract_options!
108
+ options.keys.each { |key| _permitted_allow_deny_option!(key) }
109
+
110
+ _set_action_clause( _retrieve_only(options), options.delete(:except))
111
+
112
+ object_s = _role_object_s(options)
113
+
114
+ role_checks = args.map do |who|
115
+ case who
116
+ when anonymous then "#{_subject_ref}.nil?"
117
+ when logged_in then "!#{_subject_ref}.nil?"
118
+ when all then "true"
119
+ else
120
+ "!#{_subject_ref}.nil? && #{_subject_ref}.has_role?('#{who}'#{object_s})"
121
+ end
122
+ end
123
+
124
+ [:if, :unless].each do |cond|
125
+ val = options[cond]
126
+ raise ArgumentError, "#{cond} option must be a Symbol" if val && !val.is_a?(Symbol)
127
+ end
128
+
129
+ condition = [
130
+ (_method_ref(options[:if]) if options[:if]),
131
+ ("!#{_method_ref(options[:unless])}" if options[:unless])
132
+ ].compact.join(' && ')
133
+
134
+ condition = nil if condition.blank?
135
+
136
+ _add_rule(case role_checks.size
137
+ when 0
138
+ raise ArgumentError, "allow/deny should have at least 1 argument"
139
+ when 1 then role_checks.first
140
+ else
141
+ _either_of(role_checks)
142
+ end, condition)
143
+ end
144
+
145
+ def _either_of(exprs)
146
+ clause = exprs.map { |expr| "(#{expr})" }.join(' || ')
147
+ return "(#{clause})"
148
+ end
149
+
150
+ def _add_rule(what, condition)
151
+ anded = [what] + [@action_clause, condition].compact
152
+ anded[0] = "(#{anded[0]})" if anded.size > 1
153
+
154
+ (@current_rule == :allow ? @allows : @denys) << anded.join(' && ')
155
+ end
156
+
157
+ def _set_action_clause(only, except)
158
+ raise ArgumentError, "both :only (:to) and :except cannot be specified in the rule" if only && except
159
+
160
+ @action_clause = nil
161
+ action_list = only || except
162
+ return unless action_list
163
+
164
+ expr = _action_check_expression(action_list)
165
+ @action_clause = only ? "#{expr}" : "!#{expr}"
166
+ end
167
+
168
+ def _action_check_expression(action_list)
169
+ unless action_list.is_a?(Array)
170
+ action_list = [ action_list.to_s ]
171
+ end
172
+
173
+ case action_list.size
174
+ when 0 then "true"
175
+ when 1 then "(#{_action_ref} == '#{action_list.first}')"
176
+ else
177
+ set_of_actions = "Set.new([" + action_list.map { |act| "'#{act}'"}.join(',') + "])"
178
+
179
+ "#{set_of_actions}.include?(#{_action_ref})"
180
+ end
181
+ end
182
+
183
+ def _role_object_s(options)
184
+ object = _by_preposition options
185
+
186
+ case object
187
+ when Class then ", #{object}"
188
+ when Symbol then ", #{_object_ref object}"
189
+ when nil then ""
190
+ else
191
+ raise ArgumentError, "object specified by preposition can only be a Class or a Symbol"
192
+ end
193
+ end
194
+
195
+ def _subject_ref
196
+ raise
197
+ end
198
+
199
+ def _object_ref(object)
200
+ raise
201
+ end
202
+
203
+ def _action_ref
204
+ raise
205
+ end
206
+
207
+ def _method_ref(method)
208
+ raise
209
+ end
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,166 @@
1
+ require_relative "dsl_base"
2
+
3
+ module Acl9
4
+ module Dsl
5
+ module Generators
6
+ class BaseGenerator < Acl9::Dsl::Base
7
+ def initialize(*args)
8
+ @subject_method = args[0]
9
+
10
+ super
11
+ end
12
+
13
+ protected
14
+
15
+ def _access_denied
16
+ "raise Acl9::AccessDenied"
17
+ end
18
+
19
+ def _subject_ref
20
+ "#{_controller_ref}send(:#{@subject_method})"
21
+ end
22
+
23
+ def _object_ref(object)
24
+ "#{_controller_ref}instance_variable_get('@#{object}')"
25
+ end
26
+
27
+ def _action_ref
28
+ "#{_controller_ref}action_name"
29
+ end
30
+
31
+ def _method_ref(method)
32
+ "#{_controller_ref}send(:#{method})"
33
+ end
34
+
35
+ def _controller_ref
36
+ @controller ? "#{@controller}." : ''
37
+ end
38
+
39
+ def install_on(controller_class, options)
40
+ debug_dump(controller_class) if options[:debug]
41
+ end
42
+
43
+ def debug_dump(klass)
44
+ return unless logger
45
+ logger.debug "=== Acl9 access_control expression dump (#{klass.to_s})"
46
+ logger.debug self.to_s
47
+ logger.debug "======"
48
+ end
49
+
50
+ def logger
51
+ ActionController::Base.logger
52
+ end
53
+ end
54
+
55
+ class FilterLambda < BaseGenerator
56
+ def initialize(subject_method)
57
+ super
58
+
59
+ @controller = 'controller'
60
+ end
61
+
62
+ def install_on(controller_class, options)
63
+ super
64
+
65
+ controller_class.send(:before_action, options, &self.to_proc)
66
+ end
67
+
68
+ def to_proc
69
+ code = <<-RUBY
70
+ lambda do |controller|
71
+ unless #{allowance_expression}
72
+ #{_access_denied}
73
+ end
74
+ end
75
+ RUBY
76
+
77
+ self.instance_eval(code, __FILE__, __LINE__)
78
+ rescue SyntaxError
79
+ raise FilterSyntaxError, code
80
+ end
81
+ end
82
+
83
+ ################################################################
84
+
85
+ class FilterMethod < BaseGenerator
86
+ def initialize(subject_method, method_name)
87
+ super
88
+
89
+ @method_name = method_name
90
+ @controller = nil
91
+ end
92
+
93
+ def install_on(controller_class, options)
94
+ super
95
+ _add_method(controller_class)
96
+ controller_class.send(:before_action, @method_name, options)
97
+ end
98
+
99
+ protected
100
+
101
+ def _add_method(controller_class)
102
+ code = self.to_method_code
103
+ controller_class.send(:class_eval, code, __FILE__, __LINE__)
104
+ rescue SyntaxError
105
+ raise FilterSyntaxError, code
106
+ end
107
+
108
+ def to_method_code
109
+ <<-RUBY
110
+ def #{@method_name}
111
+ unless #{allowance_expression}
112
+ #{_access_denied}
113
+ end
114
+ end
115
+ RUBY
116
+ end
117
+ end
118
+
119
+ ################################################################
120
+
121
+ class BooleanMethod < FilterMethod
122
+ def install_on(controller_class, opts)
123
+ debug_dump(controller_class) if opts[:debug]
124
+
125
+ _add_method(controller_class)
126
+
127
+ if opts[:helper]
128
+ controller_class.send(:helper_method, @method_name)
129
+ end
130
+ end
131
+
132
+ protected
133
+
134
+ def to_method_code
135
+ <<-RUBY
136
+ def #{@method_name}(*args)
137
+ options = args.extract_options!
138
+
139
+ unless args.size <= 1
140
+ raise ArgumentError, "call #{@method_name} with 0, 1 or 2 arguments"
141
+ end
142
+
143
+ self.action_name = args.first.to_s if args.present?
144
+
145
+ return #{allowance_expression}
146
+ end
147
+ RUBY
148
+ end
149
+
150
+ def _object_ref(object)
151
+ "(options[:#{object}] || #{super})"
152
+ end
153
+ end
154
+
155
+ ################################################################
156
+
157
+ class HelperMethod < BooleanMethod
158
+ def initialize(subject_method, method)
159
+ super
160
+
161
+ @controller = 'controller'
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,85 @@
1
+ require_relative "controller_extensions/generators"
2
+
3
+ module Acl9
4
+ module ControllerExtensions
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def access_control(*args, &block)
11
+ opts = args.extract_options!
12
+
13
+ case args.size
14
+ when 0 then true
15
+ when 1
16
+ meth = args.first
17
+
18
+ if meth.is_a? Symbol
19
+ opts[:as_method] = meth
20
+ else
21
+ raise ArgumentError, "access_control argument must be a :symbol!"
22
+ end
23
+ else
24
+ raise ArgumentError, "Invalid arguments for access_control"
25
+ end
26
+
27
+ subject_method = opts[:subject_method] || Acl9::config[:default_subject_method]
28
+
29
+ raise ArgumentError, "Block must be supplied to access_control" unless block
30
+
31
+ filter = opts[:filter]
32
+ filter = true if filter.nil?
33
+
34
+ case helper = opts[:helper]
35
+ when true
36
+ raise ArgumentError, "you should specify :helper => :method_name" if !opts[:as_method]
37
+ when nil then nil
38
+ else
39
+ if opts[:as_method]
40
+ raise ArgumentError, "you can't specify both method name and helper name"
41
+ else
42
+ opts[:as_method] = helper
43
+ filter = false
44
+ end
45
+ end
46
+
47
+ method = opts[:as_method]
48
+
49
+ query_method_available = true
50
+ generator = case
51
+ when method && filter
52
+ Acl9::Dsl::Generators::FilterMethod.new(subject_method, method)
53
+ when method && !filter
54
+ query_method_available = false
55
+ Acl9::Dsl::Generators::BooleanMethod.new(subject_method, method)
56
+ else
57
+ Acl9::Dsl::Generators::FilterLambda.new(subject_method)
58
+ end
59
+
60
+ generator.acl_block!(&block)
61
+
62
+ generator.install_on(self, opts)
63
+
64
+ if query_method_available && (query_method = opts.delete(:query_method))
65
+ case query_method
66
+ when true
67
+ if method
68
+ query_method = "#{method}?"
69
+ else
70
+ raise ArgumentError, "You must specify :query_method as Symbol"
71
+ end
72
+ when Symbol, String
73
+ # okay here
74
+ else
75
+ raise ArgumentError, "Invalid value for :query_method"
76
+ end
77
+
78
+ second_generator = Acl9::Dsl::Generators::BooleanMethod.new(subject_method, query_method)
79
+ second_generator.acl_block!(&block)
80
+ second_generator.install_on(self, opts)
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,49 @@
1
+ module Acl9
2
+ module Helpers
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def access_control(method, opts = {}, &block)
9
+ subject_method = opts.delete(:subject_method) || Acl9::config[:default_subject_method]
10
+ raise ArgumentError, "Block must be supplied to access_control" unless block
11
+
12
+ generator = Acl9::Dsl::Generators::HelperMethod.new(subject_method, method)
13
+
14
+ generator.acl_block!(&block)
15
+ generator.install_on(self, opts)
16
+ end
17
+
18
+ end
19
+
20
+ # Usage:
21
+ #
22
+ # <%=show_to(:owner, :supervisor, :of => :account) do %>
23
+ # <%= 'hello' %>
24
+ # <% end %>
25
+ #
26
+ def show_to(*args, &block)
27
+ user = send(Acl9.config[:default_subject_method])
28
+ return if user.nil?
29
+
30
+ has_any = false
31
+
32
+ if args.last.is_a?(Hash)
33
+ an_obj = args.pop.values.first
34
+ has_any = args.detect { |role| user.has_role?(role, an_obj) }
35
+ else
36
+ has_any = args.detect { |role| user.has_role?(role) }
37
+ end
38
+
39
+ if has_any
40
+ begin
41
+ capture( &block )
42
+ rescue NoMethodError
43
+ yield( :block )
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,74 @@
1
+ module Acl9
2
+ module ModelExtensions
3
+ module ForObject
4
+ ##
5
+ # Role check.
6
+ #
7
+ # @return [Boolean] Returns true if +subject+ has a role +role_name+ on this object.
8
+ #
9
+ # @param [Symbol,String] role_name Role name
10
+ # @param [Subject] subject Subject to add role for
11
+ # @see Acl9::ModelExtensions::Subject#has_role?
12
+ def accepts_role?(role_name, subject)
13
+ if not subject.nil?
14
+ return subject.has_role? role_name, self
15
+ end
16
+ false
17
+ end
18
+
19
+ ##
20
+ # Add role on the object to specified subject.
21
+ #
22
+ # @param [Symbol,String] role_name Role name
23
+ # @param [Subject] subject Subject to add role for
24
+ # @see Acl9::ModelExtensions::Subject#has_role!
25
+ def accepts_role!(role_name, subject)
26
+ if not subject.nil?
27
+ return subject.has_role! role_name, self
28
+ end
29
+ false
30
+ end
31
+
32
+ ##
33
+ # Free specified subject of a role on this object.
34
+ #
35
+ # @param [Symbol,String] role_name Role name
36
+ # @param [Subject] subject Subject to remove role from
37
+ # @see Acl9::ModelExtensions::Subject#has_no_role!
38
+ def accepts_no_role!(role_name, subject)
39
+ if not subject.nil?
40
+ return subject.has_no_role! role_name, self
41
+ end
42
+ false
43
+ end
44
+
45
+ ##
46
+ # Are there any roles for the specified +subject+ on this object?
47
+ #
48
+ # @param [Subject] subject Subject to query roles
49
+ # @return [Boolean] Returns true if +subject+ has any roles on this object.
50
+ # @see Acl9::ModelExtensions::Subject#has_roles_for?
51
+ def accepts_roles_by?(subject)
52
+ if not subject.nil?
53
+ return subject.has_roles_for? self
54
+ end
55
+ false
56
+ end
57
+
58
+ alias :accepts_role_by? :accepts_roles_by?
59
+
60
+ ##
61
+ # Which roles does +subject+ have on this object?
62
+ #
63
+ # @return [Array<Role>] Role instances, associated both with +subject+ and +object+
64
+ # @param [Subject] subject Subject to query roles
65
+ # @see Acl9::ModelExtensions::Subject#roles_for
66
+ def accepted_roles_by(subject)
67
+ if not subject.nil?
68
+ return subject.roles_for self
69
+ end
70
+ false
71
+ end
72
+ end
73
+ end
74
+ end