acl9 2.1.0 → 3.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +3 -0
  3. data/.ruby-version +1 -1
  4. data/.travis.yml +27 -11
  5. data/Appraisals +13 -6
  6. data/Gemfile +0 -2
  7. data/Gemfile.lock +125 -112
  8. data/README.md +11 -4
  9. data/Rakefile +0 -2
  10. data/acl9.gemspec +1 -3
  11. data/gemfiles/.bundle/config +2 -0
  12. data/gemfiles/rails_5.0.gemfile +10 -0
  13. data/gemfiles/rails_5.1.gemfile +10 -0
  14. data/gemfiles/{rails_4.0.gemfile → rails_5.2.gemfile} +2 -4
  15. data/gemfiles/{rails_4.1.gemfile → rails_6.0.gemfile} +2 -4
  16. data/gemfiles/{rails_4.2.gemfile → rails_6.1.gemfile} +2 -4
  17. data/lib/acl9.rb +40 -0
  18. data/lib/acl9/controller_extensions.rb +1 -1
  19. data/lib/acl9/controller_extensions/dsl_base.rb +8 -7
  20. data/lib/acl9/controller_extensions/generators.rb +4 -35
  21. data/lib/acl9/model_extensions.rb +3 -3
  22. data/lib/acl9/model_extensions/for_subject.rb +52 -31
  23. data/lib/acl9/version.rb +1 -1
  24. data/lib/generators/acl9/setup/setup_generator.rb +10 -3
  25. data/lib/generators/acl9/setup/templates/create_role_tables.rb +10 -1
  26. data/lib/generators/acl9/setup/templates/role.rb +1 -1
  27. data/test/controller_extensions/actions_test.rb +1 -1
  28. data/test/controller_extensions/multiple_role_arguments_test.rb +11 -10
  29. data/test/controllers/acl_action_override_test.rb +4 -4
  30. data/test/controllers/acl_helper_method_test.rb +6 -3
  31. data/test/controllers/acl_ivars_test.rb +2 -2
  32. data/test/controllers/acl_object_hash_test.rb +1 -1
  33. data/test/controllers/acl_query_mixin.rb +5 -2
  34. data/test/controllers/acl_subject_method_test.rb +1 -1
  35. data/test/controllers/arguments_checking_test.rb +4 -4
  36. data/test/dummy/app/assets/config/manifest.js +0 -0
  37. data/test/dummy/app/controllers/acl_action_override.rb +5 -5
  38. data/test/dummy/app/controllers/acl_boolean_method.rb +6 -6
  39. data/test/dummy/app/controllers/acl_ivars.rb +3 -3
  40. data/test/dummy/app/controllers/acl_query_method_named.rb +2 -0
  41. data/test/dummy/app/controllers/application_controller.rb +6 -0
  42. data/test/dummy/app/controllers/empty_controller.rb +1 -1
  43. data/test/dummy/app/models/string_object_role.rb +3 -0
  44. data/test/dummy/app/models/string_user.rb +3 -0
  45. data/test/dummy/app/models/uuid.rb +1 -1
  46. data/test/dummy/config/environments/test.rb +2 -2
  47. data/test/dummy/config/routes.rb +12 -1
  48. data/test/dummy/db/migrate/20141117132218_create_tables.rb +68 -18
  49. data/test/models/roles_test.rb +13 -1
  50. data/test/test_helper.rb +31 -28
  51. metadata +26 -29
  52. data/test/dummy/config/environments/production.rb +0 -78
@@ -0,0 +1,10 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "appraisal"
6
+ gem "byebug"
7
+ gem "rails", "~> 5.1.0"
8
+ gem "sqlite3", "~> 1.3.6", :group => :development
9
+
10
+ gemspec path: "../"
@@ -3,9 +3,7 @@
3
3
  source "http://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
- gem "tapout"
7
- gem "minitap"
8
6
  gem "byebug"
9
- gem "rails", "~> 4.0.0"
7
+ gem "rails", "~> 5.2.0"
10
8
 
11
- gemspec :path => "../"
9
+ gemspec path: "../"
@@ -3,9 +3,7 @@
3
3
  source "http://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
- gem "tapout"
7
- gem "minitap"
8
6
  gem "byebug"
9
- gem "rails", "~> 4.1.0"
7
+ gem "rails", "~> 6.0.0"
10
8
 
11
- gemspec :path => "../"
9
+ gemspec path: "../"
@@ -3,9 +3,7 @@
3
3
  source "http://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
- gem "tapout"
7
- gem "minitap"
8
6
  gem "byebug"
9
- gem "rails", "~> 4.2.0"
7
+ gem "rails", "~> 6.1.0"
10
8
 
11
- gemspec :path => "../"
9
+ gemspec path: "../"
data/lib/acl9.rb CHANGED
@@ -22,6 +22,10 @@ module Acl9
22
22
  send "#{k}=", v
23
23
  end
24
24
  end
25
+
26
+ def merge! h
27
+ h.each { |k,v| self[k.to_sym] = v }
28
+ end
25
29
  end
26
30
 
27
31
  @@config = Config.new( *CONFIG.values_at(*Config.members))
@@ -31,6 +35,42 @@ module Acl9
31
35
  def self.configure
32
36
  yield config
33
37
  end
38
+
39
+ class ArgumentError < ArgumentError; end
40
+ class RuntimeError < RuntimeError; end
41
+ class NilObjectError < RuntimeError; end
42
+
43
+ ##
44
+ # This exception is raised whenever ACL block finds that the current user
45
+ # is not authorized for the controller action he wants to execute.
46
+ # @example How to catch this exception in ApplicationController
47
+ # class ApplicationController < ActionController::Base
48
+ # rescue_from 'Acl9::AccessDenied', :with => :access_denied
49
+ #
50
+ # # ...other stuff...
51
+ # private
52
+ #
53
+ # def access_denied
54
+ # if current_user
55
+ # # It's presumed you have a template with words of pity and regret
56
+ # # for unhappy user who is not authorized to do what he wanted
57
+ # render :template => 'home/access_denied'
58
+ # else
59
+ # # In this case user has not even logged in. Might be OK after login.
60
+ # flash[:notice] = 'Access denied. Try to log in first.'
61
+ # redirect_to login_path
62
+ # end
63
+ # end
64
+ # end
65
+ #
66
+ class AccessDenied < RuntimeError; end
67
+
68
+ ##
69
+ # This exception is raised when acl9 has generated invalid code for the
70
+ # filtering method or block. Should never happen, and it's a bug when it
71
+ # happens.
72
+ class FilterSyntaxError < ArgumentError; end
73
+
34
74
  end
35
75
 
36
76
  ActiveRecord::Base.send(:include, Acl9::ModelExtensions)
@@ -1,4 +1,4 @@
1
- require File.join(File.dirname(__FILE__), 'controller_extensions', 'generators')
1
+ require_relative "controller_extensions/generators"
2
2
 
3
3
  module Acl9
4
4
  module ControllerExtensions
@@ -1,4 +1,4 @@
1
- require File.expand_path '../../prepositions', __FILE__
1
+ require_relative "../prepositions"
2
2
 
3
3
  module Acl9
4
4
  module Dsl
@@ -12,6 +12,7 @@ module Acl9
12
12
  @allows = []
13
13
  @denys = []
14
14
  @original_args = args
15
+ @action_clause = nil
15
16
  end
16
17
 
17
18
  def acl_block!(&acl_block)
@@ -108,7 +109,7 @@ module Acl9
108
109
 
109
110
  _set_action_clause( _retrieve_only(options), options.delete(:except))
110
111
 
111
- object = _role_object(options)
112
+ object_s = _role_object_s(options)
112
113
 
113
114
  role_checks = args.map do |who|
114
115
  case who
@@ -116,7 +117,7 @@ module Acl9
116
117
  when logged_in then "!#{_subject_ref}.nil?"
117
118
  when all then "true"
118
119
  else
119
- "!#{_subject_ref}.nil? && #{_subject_ref}.has_role?('#{who}', #{object})"
120
+ "!#{_subject_ref}.nil? && #{_subject_ref}.has_role?('#{who}'#{object_s})"
120
121
  end
121
122
  end
122
123
 
@@ -179,13 +180,13 @@ module Acl9
179
180
  end
180
181
  end
181
182
 
182
- def _role_object(options)
183
+ def _role_object_s(options)
183
184
  object = _by_preposition options
184
185
 
185
186
  case object
186
- when Class then object.to_s
187
- when Symbol then _object_ref object
188
- when nil then "nil"
187
+ when Class then ", #{object}"
188
+ when Symbol then ", #{_object_ref object}"
189
+ when nil then ""
189
190
  else
190
191
  raise ArgumentError, "object specified by preposition can only be a Class or a Symbol"
191
192
  end
@@ -1,37 +1,6 @@
1
- require File.join(File.dirname(__FILE__), 'dsl_base')
1
+ require_relative "dsl_base"
2
2
 
3
3
  module Acl9
4
- ##
5
- # This exception is raised whenever ACL block finds that the current user
6
- # is not authorized for the controller action he wants to execute.
7
- # @example How to catch this exception in ApplicationController
8
- # class ApplicationController < ActionController::Base
9
- # rescue_from 'Acl9::AccessDenied', :with => :access_denied
10
- #
11
- # # ...other stuff...
12
- # private
13
- #
14
- # def access_denied
15
- # if current_user
16
- # # It's presumed you have a template with words of pity and regret
17
- # # for unhappy user who is not authorized to do what he wanted
18
- # render :template => 'home/access_denied'
19
- # else
20
- # # In this case user has not even logged in. Might be OK after login.
21
- # flash[:notice] = 'Access denied. Try to log in first.'
22
- # redirect_to login_path
23
- # end
24
- # end
25
- # end
26
- #
27
- class AccessDenied < StandardError; end
28
-
29
- ##
30
- # This exception is raised when acl9 has generated invalid code for the
31
- # filtering method or block. Should never happen, and it's a bug when it
32
- # happens.
33
- class FilterSyntaxError < StandardError; end
34
-
35
4
  module Dsl
36
5
  module Generators
37
6
  class BaseGenerator < Acl9::Dsl::Base
@@ -93,7 +62,7 @@ module Acl9
93
62
  def install_on(controller_class, options)
94
63
  super
95
64
 
96
- controller_class.send(:before_filter, options, &self.to_proc)
65
+ controller_class.send(:before_action, options, &self.to_proc)
97
66
  end
98
67
 
99
68
  def to_proc
@@ -124,7 +93,7 @@ module Acl9
124
93
  def install_on(controller_class, options)
125
94
  super
126
95
  _add_method(controller_class)
127
- controller_class.send(:before_filter, @method_name, options)
96
+ controller_class.send(:before_action, @method_name, options)
128
97
  end
129
98
 
130
99
  protected
@@ -171,7 +140,7 @@ module Acl9
171
140
  raise ArgumentError, "call #{@method_name} with 0, 1 or 2 arguments"
172
141
  end
173
142
 
174
- action_name = args.empty? ? self.action_name : args.first.to_s
143
+ self.action_name = args.first.to_s if args.present?
175
144
 
176
145
  return #{allowance_expression}
177
146
  end
@@ -1,5 +1,5 @@
1
- require File.join(File.dirname(__FILE__), 'model_extensions', 'for_subject')
2
- require File.join(File.dirname(__FILE__), 'model_extensions', 'for_object')
1
+ require_relative "model_extensions/for_subject"
2
+ require_relative "model_extensions/for_object"
3
3
 
4
4
  module Acl9
5
5
  module ModelExtensions #:nodoc:
@@ -129,7 +129,7 @@ module Acl9
129
129
  :class_name => subject,
130
130
  :join_table => join_table
131
131
 
132
- belongs_to :authorizable, :polymorphic => true
132
+ belongs_to :authorizable, polymorphic: true, optional: true
133
133
  end
134
134
  end
135
135
  end
@@ -1,10 +1,16 @@
1
- require File.expand_path '../../prepositions', __FILE__
1
+ require_relative "../prepositions"
2
2
 
3
3
  module Acl9
4
4
  module ModelExtensions
5
5
  module ForSubject
6
6
  include Prepositions
7
7
 
8
+ DEFAULT = Class.new do
9
+ def default?
10
+ true
11
+ end
12
+ end.new.freeze
13
+
8
14
  ##
9
15
  # Role check.
10
16
  #
@@ -38,16 +44,17 @@ module Acl9
38
44
  # @param [Object] object Object to query a role on
39
45
  #
40
46
  # @see Acl9::ModelExtensions::Object#accepts_role?
41
- def has_role?(role_name, object = nil)
47
+ def has_role?(role_name, object = default)
48
+ check! object
42
49
  role_name = normalize role_name
43
50
  object = _by_preposition object
44
51
 
45
- !! if object.nil? && !::Acl9.config[:protect_global_roles]
46
- self._role_objects.find_by_name(role_name.to_s) ||
47
- self._role_objects.member?(get_role(role_name, nil))
52
+ !! if object == default && !::Acl9.config[:protect_global_roles]
53
+ _role_objects.find_by_name(role_name.to_s) ||
54
+ _role_objects.member?(get_role(role_name, object))
48
55
  else
49
56
  role = get_role(role_name, object)
50
- role && self._role_objects.exists?(role.id)
57
+ role && _role_objects.exists?(role.id)
51
58
  end
52
59
  end
53
60
 
@@ -57,7 +64,8 @@ module Acl9
57
64
  # @param [Symbol,String] role_name Role name
58
65
  # @param [Object] object Object to add a role for
59
66
  # @see Acl9::ModelExtensions::Object#accepts_role!
60
- def has_role!(role_name, object = nil)
67
+ def has_role!(role_name, object = default)
68
+ check! object
61
69
  role_name = normalize role_name
62
70
  object = _by_preposition object
63
71
 
@@ -65,15 +73,15 @@ module Acl9
65
73
 
66
74
  if role.nil?
67
75
  role_attrs = case object
68
- when Class then { :authorizable_type => object.to_s }
69
- when nil then {}
70
- else { :authorizable => object }
71
- end.merge( { :name => role_name.to_s })
76
+ when Class then { :authorizable_type => object.to_s }
77
+ when default then {}
78
+ else { :authorizable => object }
79
+ end.merge({ :name => role_name.to_s })
72
80
 
73
- role = self._auth_role_class.create(role_attrs)
81
+ role = _auth_role_class.create(role_attrs)
74
82
  end
75
83
 
76
- self._role_objects << role if role && !self._role_objects.exists?(role.id)
84
+ _role_objects << role if role && !_role_objects.exists?(role.id)
77
85
  end
78
86
 
79
87
  ##
@@ -82,7 +90,8 @@ module Acl9
82
90
  # @param [Symbol,String] role_name Role name
83
91
  # @param [Object] object Object to remove a role on
84
92
  # @see Acl9::ModelExtensions::Object#accepts_no_role!
85
- def has_no_role!(role_name, object = nil)
93
+ def has_no_role!(role_name, object = default)
94
+ check! object
86
95
  role_name = normalize role_name
87
96
  object = _by_preposition object
88
97
  delete_role(get_role(role_name, object))
@@ -95,7 +104,8 @@ module Acl9
95
104
  # @return [Boolean] Returns true if +self+ has any roles on +object+.
96
105
  # @see Acl9::ModelExtensions::Object#accepts_roles_by?
97
106
  def has_roles_for?(object)
98
- !!self._role_objects.detect(&role_selecting_lambda(object))
107
+ check! object
108
+ !!_role_objects.detect(&role_selecting_lambda(object))
99
109
  end
100
110
 
101
111
  alias :has_role_for? :has_roles_for?
@@ -112,14 +122,16 @@ module Acl9
112
122
  #
113
123
  # user.roles_for(product).map(&:name).sort #=> role names in alphabetical order
114
124
  def roles_for(object)
115
- self._role_objects.select(&role_selecting_lambda(object))
125
+ check! object
126
+ _role_objects.select(&role_selecting_lambda(object))
116
127
  end
117
128
 
118
129
  ##
119
130
  # Unassign any roles on +object+ from +self+.
120
131
  #
121
- # @param [Object,nil] object Object to unassign roles for. +nil+ means unassign global roles.
122
- def has_no_roles_for!(object = nil)
132
+ # @param [Object,default] object Object to unassign roles for. Empty args means unassign global roles.
133
+ def has_no_roles_for!(object = default)
134
+ check! object
123
135
  roles_for(object).each { |role| delete_role(role) }
124
136
  end
125
137
 
@@ -128,11 +140,11 @@ module Acl9
128
140
  def has_no_roles!
129
141
  # for some reason simple
130
142
  #
131
- # self.roles.each { |role| delete_role(role) }
143
+ # roles.each { |role| delete_role(role) }
132
144
  #
133
145
  # doesn't work. seems like a bug in ActiveRecord
134
- self._role_objects.map(&:id).each do |role_id|
135
- delete_role self._auth_role_class.find(role_id)
146
+ _role_objects.map(&:id).each do |role_id|
147
+ delete_role _auth_role_class.find(role_id)
136
148
  end
137
149
  end
138
150
 
@@ -142,7 +154,7 @@ module Acl9
142
154
  case object
143
155
  when Class
144
156
  lambda { |role| role.authorizable_type == object.to_s }
145
- when nil
157
+ when default
146
158
  lambda { |role| role.authorizable.nil? }
147
159
  else
148
160
  lambda do |role|
@@ -152,13 +164,14 @@ module Acl9
152
164
  end
153
165
  end
154
166
 
155
- def get_role(role_name, object)
167
+ def get_role(role_name, object = default)
168
+ check! object
156
169
  role_name = normalize role_name
157
170
 
158
171
  cond = case object
159
172
  when Class
160
173
  [ 'name = ? and authorizable_type = ? and authorizable_id IS NULL', role_name, object.to_s ]
161
- when nil
174
+ when default
162
175
  [ 'name = ? and authorizable_type IS NULL and authorizable_id IS NULL', role_name ]
163
176
  else
164
177
  [
@@ -167,17 +180,17 @@ module Acl9
167
180
  ]
168
181
  end
169
182
 
170
- if self._auth_role_class.respond_to?(:where)
171
- self._auth_role_class.where(cond).first
183
+ if _auth_role_class.respond_to?(:where)
184
+ _auth_role_class.where(cond).first
172
185
  else
173
- self._auth_role_class.find(:first, :conditions => cond)
186
+ _auth_role_class.find(:first, :conditions => cond)
174
187
  end
175
188
  end
176
189
 
177
190
  def delete_role(role)
178
191
  if role
179
- if ret = self._role_objects.delete(role)
180
- if role.send(self._auth_subject_class_name.demodulize.tableize).empty?
192
+ if ret = _role_objects.delete(role)
193
+ if role.send(_auth_subject_class_name.demodulize.tableize).empty?
181
194
  ret &&= role.destroy unless role.respond_to?(:system?) && role.system?
182
195
  end
183
196
  end
@@ -189,7 +202,11 @@ module Acl9
189
202
  Acl9.config[:normalize_role_names] ? role_name.to_s.underscore.singularize : role_name.to_s
190
203
  end
191
204
 
192
- protected
205
+ private
206
+
207
+ def check! object
208
+ raise NilObjectError if object.nil?
209
+ end
193
210
 
194
211
  def _by_preposition object
195
212
  object.is_a?(Hash) ? super : object
@@ -204,7 +221,11 @@ module Acl9
204
221
  end
205
222
 
206
223
  def _role_objects
207
- send(self._auth_role_assoc)
224
+ send(_auth_role_assoc)
225
+ end
226
+
227
+ def default
228
+ DEFAULT
208
229
  end
209
230
  end
210
231
  end
data/lib/acl9/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Acl9
2
- VERSION = "2.1.0"
2
+ VERSION = "3.2.0"
3
3
  end
@@ -10,9 +10,8 @@ module Acl9
10
10
  argument :arg_role, type: :string, default: 'role', banner: "role"
11
11
  argument :arg_objects, type: :array, default: [], banner: "objects..."
12
12
 
13
- def create_migration
14
- next_migration_number = self.class.next_migration_number( File.expand_path( '../db/migrate', __FILE__))
15
- template "create_role_tables.rb", "db/migrate/#{next_migration_number}_create_#{role_name}_tables.rb"
13
+ def create_migration_file
14
+ migration_template "create_role_tables.rb", File.join(db_migrate_path, "create_#{role_name}_tables.rb")
16
15
  end
17
16
 
18
17
  def create_models
@@ -56,6 +55,14 @@ module Acl9
56
55
  role_name.classify
57
56
  end
58
57
 
58
+ def model_base_name
59
+ r5? ? ApplicationRecord : ActiveRecord::Base
60
+ end
61
+
62
+ def r5?
63
+ Rails.gem_version >= Gem::Version.new(5)
64
+ end
65
+
59
66
  def habtm_table
60
67
  Acl9.config.default_join_table_name || [ subject_name, role_name ].map(&:pluralize).sort.join('_')
61
68
  end