acl9 3.0.0 → 3.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 105b1a050bdefc20d0671c4035500f9abd99f8f588b69ed3ceb3357f61ea01e1
4
- data.tar.gz: 2e5f73791a47de3e9fe4148c81868d6befcda7075163813eb86877c7e21084a5
3
+ metadata.gz: 7ee10c2f6e3894b825f17a575524a0343dcdf16217a3049b665e04da980bce1c
4
+ data.tar.gz: cd72c5c1e1983b28e8799c9792e5fa843f89415e104588feaf2dbeb72fd1f651
5
5
  SHA512:
6
- metadata.gz: 9caadac85342a7885a46581b4a60fc7c83d51b23c50f85e0e2121fa2d15fd4ab0383984f5f7b48076f18dd49409ad40e5292f9d8a2615aced3088f0f004c28b0
7
- data.tar.gz: edec0e425c0dfaf67f934b9a79ae37e3fad11baeedb605c04ccf0533bc59d1e3c4851f41f2d909cec855310fe69f811f0ff9aec78755ee3fb8a52c61e47a698d
6
+ metadata.gz: dca2492214e239e447b4de8f1874be52c617ca361fdcbc79ac5f4c58782ff92449e29db54f9618356680c96e55023412a6206e1f9b3ec9d7f20074d7cb89d76d
7
+ data.tar.gz: 0a8963681d65a13fd39e3d4e46d75be288fda1a3ce1a8bb05c1e6264da2e1601c0abb698dbbfd9abe10e965bd6c0491acab62131852f508ad3c2b1d852f3cdc8
@@ -8,8 +8,10 @@ rvm:
8
8
  gemfile:
9
9
  - gemfiles/rails_5.0.gemfile
10
10
  - gemfiles/rails_5.1.gemfile
11
+ - gemfiles/rails_5.2.gemfile
11
12
 
12
13
  matrix:
13
14
  fast_finish: true
14
15
  allow_failures:
15
16
  - rvm: ruby-head
17
+ - gemfile: gemfiles/rails_5.2.gemfile
data/Appraisals CHANGED
@@ -5,3 +5,7 @@ end
5
5
  appraise "rails-5.1" do
6
6
  gem 'rails', '~> 5.1.0'
7
7
  end
8
+
9
+ appraise "rails-5.2" do
10
+ gem 'rails', '~> 5.2.0.rc1'
11
+ end
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- acl9 (2.1.2)
5
- rails (>= 4.0)
4
+ acl9 (3.1.0)
5
+ rails (~> 5.0)
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # acl9
2
2
 
3
- [![Travis-CI](https://travis-ci.org/be9/acl9.svg?branch=master)](https://travis-ci.org/be9/acl9) [![Code Climate](https://codeclimate.com/github/be9/acl9/badges/gpa.svg)](https://codeclimate.com/github/be9/acl9) [![Test Coverage](https://codeclimate.com/github/be9/acl9/badges/coverage.svg)](https://codeclimate.com/github/be9/acl9)
3
+ [![Travis-CI](https://travis-ci.org/be9/acl9.svg?branch=master)](https://travis-ci.org/be9/acl9)
4
4
 
5
5
  Acl9 is a role-based authorization system that provides a concise DSL for
6
6
  securing your Rails application.
@@ -16,11 +16,19 @@ Acl9 is [Semantically Versioned](http://semver.org/), so just add this to your
16
16
  `Gemfile`:
17
17
 
18
18
  ```ruby
19
- gem 'acl9', '~> 2.0'
19
+ gem 'acl9', '~> 3.0'
20
20
  ```
21
21
 
22
22
  You will need Ruby 2.x
23
23
 
24
+ ### Rails 4 - stick with 2.x
25
+
26
+ ```ruby
27
+ gem 'acl9', '~> 2.0'
28
+ ```
29
+
30
+ ### Rails < 4 - upgrade Rails!
31
+
24
32
  We dropped support for Rails < 4 in the 1.x releases, so if you're still using
25
33
  Rails 2.x or 3.x then you'll want this:
26
34
 
@@ -0,0 +1,2 @@
1
+ ---
2
+ BUNDLE_RETRY: "1"
@@ -3,6 +3,7 @@
3
3
  source "http://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
+ gem "byebug"
6
7
  gem "rails", "~> 5.0.0"
7
8
 
8
9
  gemspec path: "../"
@@ -3,6 +3,7 @@
3
3
  source "http://rubygems.org"
4
4
 
5
5
  gem "appraisal"
6
+ gem "byebug"
6
7
  gem "rails", "~> 5.1.0"
7
8
 
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", "~> 5.2.0.rc1"
8
+
9
+ gemspec path: "../"
@@ -35,6 +35,42 @@ module Acl9
35
35
  def self.configure
36
36
  yield config
37
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
+
38
74
  end
39
75
 
40
76
  ActiveRecord::Base.send(:include, Acl9::ModelExtensions)
@@ -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
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
@@ -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
@@ -5,6 +5,12 @@ module Acl9
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
@@ -1,3 +1,3 @@
1
1
  module Acl9
2
- VERSION = "3.0.0"
2
+ VERSION = "3.1.0"
3
3
  end
@@ -121,7 +121,7 @@ module ControllerExtensions
121
121
 
122
122
  assert set_all_actions
123
123
  permit_some owner, @all_actions, :foo => foo
124
- permit_some hacker, %w(show index destroy)
124
+ permit_some hacker, %w(show index destroy), foo: foo
125
125
  permit_some another_owner, %w(show index destroy), :foo => foo
126
126
  end
127
127
 
@@ -107,29 +107,30 @@ module ControllerExtensions
107
107
 
108
108
  test "should also respect :to and :except" do
109
109
  assert foo = Foo.create
110
+ assert too = Foo.create
110
111
 
111
- assert ( foo = User.create ).has_role! :foo
112
+ assert ( goo = User.create ).has_role! :goo
112
113
  assert ( joo = User.create ).has_role! :joo, foo
113
114
  assert ( qoo = User.create ).has_role! :qoo, Bar
114
115
 
115
116
  @tester.acl_block! do
116
- allow :foo, :boo, :to => [:index, :show]
117
+ allow :goo, :boo, :to => [:index, :show]
117
118
  allow :zoo, :joo, :by => :foo, :to => [:edit, :update]
118
119
  allow :qoo, :woo, :of => Bar
119
120
  deny :qoo, :woo, :of => Bar, :except => [:delete, :destroy]
120
121
  end
121
122
 
122
- assert_permitted foo, 'index'
123
- assert_permitted foo, 'show'
124
- assert_forbidden foo, 'edit'
123
+ assert_permitted goo, 'index'
124
+ assert_permitted goo, 'show'
125
+ assert_forbidden goo, 'edit', foo: too
125
126
  assert_permitted joo, 'edit', :foo => foo
126
127
  assert_permitted joo, 'update', :foo => foo
127
128
  assert_forbidden joo, 'show', :foo => foo
128
- assert_forbidden joo, 'show'
129
- assert_permitted qoo, 'delete'
130
- assert_permitted qoo, 'destroy'
131
- assert_forbidden qoo, 'edit'
132
- assert_forbidden qoo, 'show'
129
+ assert_forbidden joo, 'show', foo: foo
130
+ assert_permitted qoo, 'delete', foo: too
131
+ assert_permitted qoo, 'destroy', foo: too
132
+ assert_forbidden qoo, 'edit', foo: too
133
+ assert_forbidden qoo, 'show', foo: too
133
134
  end
134
135
  end
135
136
  end
@@ -13,10 +13,13 @@ class ACLHelperMethodTest < ActionController::TestCase
13
13
  end
14
14
 
15
15
  test "another user denied" do
16
+ assert @another = User.create
17
+ assert @another.has_role! :owner, Foo.first_or_create
18
+
16
19
  assert @user.has_role! :owner
17
20
 
18
21
  assert get :allow, params: { user_id: @user.id }
19
- assert_select 'div', 'OK'
22
+ assert_select 'div', 'AccessDenied'
20
23
  end
21
24
 
22
25
  test "anon denied" do
@@ -6,7 +6,10 @@ module ACLQueryMixin
6
6
  setup do
7
7
  assert ( @editor = User.create ).has_role! :editor
8
8
  assert ( @viewer = User.create ).has_role! :viewer
9
- assert ( @owneroffoo = User.create ).has_role! :owner, Foo.first_or_create
9
+ assert ( @foo = Foo.first_or_create )
10
+ assert ( @owneroffoo = User.create ).has_role! :owner, @foo
11
+
12
+ @controller.before_action
10
13
  end
11
14
 
12
15
  %i[edit update destroy].each do |meth|
@@ -8,6 +8,8 @@ class ACLQueryMethodNamed < ApplicationController
8
8
  end
9
9
 
10
10
  def acl?(*args)
11
+ @foo = Foo.first
12
+
11
13
  allow_ay(*args)
12
14
  end
13
15
  end
@@ -1,7 +1,13 @@
1
1
  class ApplicationController < ActionController::Base
2
+ before_action :before_action
3
+
2
4
  attr_accessor :current_user
3
5
 
4
6
  def current_user
5
7
  @current_user ||= User.find params[:user_id] if params[:user_id]
6
8
  end
9
+
10
+ def before_action
11
+ @foo = Foo.first
12
+ end
7
13
  end
@@ -13,6 +13,14 @@ class RolesTest < ActiveSupport::TestCase
13
13
  Acl9.config[:protect_global_roles] = true
14
14
  end
15
15
 
16
+ test "should not set global role with nil object" do
17
+
18
+ assert_raise Acl9::NilObjectError do
19
+ assert @user.has_role! :admin, nil
20
+ end
21
+ refute @user.has_role? :admin
22
+ end
23
+
16
24
  test "should not have any roles by default" do
17
25
  %w(user manager admin owner).each do |role|
18
26
  refute @user.has_role? role
@@ -8,11 +8,16 @@ require "rails/test_help"
8
8
  Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"]
9
9
 
10
10
  ActiveRecord::Migration.verbose = false
11
+
11
12
  ActiveRecord::Migrator.migrate File.expand_path("../dummy/db/migrate/", __FILE__)
12
13
 
13
14
  $VERBOSE = nil
14
15
 
15
16
  class ActionController::TestCase
17
+ setup do
18
+ assert Foo.create
19
+ end
20
+
16
21
  class << self
17
22
  def test_allowed method, action, params={}
18
23
  test "allowed #{method} #{action}" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: acl9
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.0
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - oleg dashevskii
@@ -92,8 +92,10 @@ files:
92
92
  - bin/yard
93
93
  - bin/yardoc
94
94
  - bin/yri
95
+ - gemfiles/.bundle/config
95
96
  - gemfiles/rails_5.0.gemfile
96
97
  - gemfiles/rails_5.1.gemfile
98
+ - gemfiles/rails_5.2.gemfile
97
99
  - lib/acl9.rb
98
100
  - lib/acl9/controller_extensions.rb
99
101
  - lib/acl9/controller_extensions/dsl_base.rb