acl9 0.11.0 → 0.12.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.
@@ -1,3 +1,17 @@
1
+ h2. 0.12.0 (04-Jan-2010)
2
+
3
+ An anniversary release of fixes and hacks, introduced by venerable users of the plugin.
4
+
5
+ * Allow for inheritance of subject (Jeff Jaco)
6
+ * Renamed "Object" module in extensions, since it caused some breakage inside activesupport
7
+ (invisiblelama).
8
+ * @show_to@ helper for usage in views (Antono Vasiljev)
9
+ * @:association_name@ config option, now you can change Subject#role_objects to whatever
10
+ you want (Jeff Tucker).
11
+ * Fix bug when Subject#id is a string, e.g. UUID (Julien Bachmann)
12
+ * Bug with action blocks when using anonymous and another role (Franck)
13
+
14
+
1
15
  h2. 0.11.0 (16-Sep-2009)
2
16
 
3
17
  * :protect_global_roles
@@ -51,12 +51,12 @@ If you have questions, please post to the
51
51
 
52
52
  h1. Installation
53
53
 
54
- Acl9 can be installed as a gem from "GitHub":http://github.com.
54
+ Acl9 can be installed as a gem from "gemcutter":http://gemcutter.org.
55
55
 
56
56
  Add the following line to your @config/environment.rb@:
57
57
 
58
58
  <pre><code>
59
- config.gem "be9-acl9", :source => "http://gems.github.com", :lib => "acl9"
59
+ config.gem "acl9", :source => "http://gemcutter.org", :lib => "acl9"
60
60
  </pre></code>
61
61
 
62
62
  Then run @rake gems:install@ (with possible @rake gems:unpack@ thereafter) and you're done!
@@ -145,11 +145,10 @@ The structure of @roles@ table is as follows:
145
145
 
146
146
  <pre><code>
147
147
  create_table "roles", :force => true do |t|
148
- t.string "name", :limit => 40
149
- t.string "authorizable_type", :limit => 40
150
- t.integer "authorizable_id"
151
- t.datetime "created_at"
152
- t.datetime "updated_at"
148
+ t.string :name, :limit => 40
149
+ t.string :authorizable_type, :limit => 40
150
+ t.integer :authorizable_id
151
+ t.timestamps
153
152
  end
154
153
  </code></pre>
155
154
 
@@ -168,10 +167,9 @@ there should be a join table:
168
167
 
169
168
  <pre><code>
170
169
  create_table "roles_users", :id => false, :force => true do |t|
171
- t.integer "user_id"
172
- t.integer "role_id"
173
- t.datetime "created_at"
174
- t.datetime "updated_at"
170
+ t.references :user
171
+ t.references :role
172
+ t.timestamps
175
173
  end
176
174
  </code></pre>
177
175
 
@@ -280,18 +278,16 @@ Note that you'll need to change your database structure appropriately:
280
278
 
281
279
  <pre><code>
282
280
  create_table "account_roles", :force => true do |t|
283
- t.string "name", :limit => 40
284
- t.string "authorizable_type", :limit => 40
285
- t.integer "authorizable_id"
286
- t.datetime "created_at"
287
- t.datetime "updated_at"
281
+ t.string :name, :limit => 40
282
+ t.string :authorizable_type, :limit => 40
283
+ t.integer :authorizable_id
284
+ t.timestamps
288
285
  end
289
286
 
290
287
  create_table "account_roles_accounts", :id => false, :force => true do |t|
291
- t.integer "account_id"
292
- t.integer "account_role_id"
293
- t.datetime "created_at"
294
- t.datetime "updated_at"
288
+ t.references :account
289
+ t.references :account_role
290
+ t.timestamps
295
291
  end
296
292
  </code></pre>
297
293
 
@@ -885,4 +881,23 @@ An imaginary view:
885
881
  <% end %>
886
882
  </code></pre>
887
883
 
888
- Copyright (c) 2009 Oleg Dashevskii, released under the MIT license.
884
+ h2. show_to in your views
885
+
886
+ @show_to@ is predefined helper for your views:
887
+
888
+ <pre><code>
889
+ <% show_to :admin, :supervisor do %>
890
+ <%= link_to 'destroy', destroy_path %>
891
+ <% end %>
892
+ </code></pre>
893
+
894
+ or even
895
+
896
+ <pre><code>
897
+ <% show_to :prince, :of => :persia do %>
898
+ <%= link_to 'Princess', princess_path %>
899
+ <% end %>
900
+ </code></pre>
901
+
902
+
903
+ Copyright (c) 2009, 2010 Oleg Dashevskii, released under the MIT license.
@@ -1,4 +1,5 @@
1
1
  ---
2
- :minor: 11
2
+ :build:
3
+ :minor: 12
3
4
  :patch: 0
4
5
  :major: 0
@@ -3,6 +3,7 @@ module Acl9
3
3
  :default_role_class_name => 'Role',
4
4
  :default_subject_class_name => 'User',
5
5
  :default_subject_method => :current_user,
6
+ :default_association_name => :role_objects,
6
7
  :protect_global_roles => false,
7
8
  }
8
9
 
@@ -142,7 +142,8 @@ module Acl9
142
142
  end
143
143
 
144
144
  def _either_of(exprs)
145
- exprs.map { |expr| "(#{expr})" }.join(' || ')
145
+ clause = exprs.map { |expr| "(#{expr})" }.join(' || ')
146
+ return "(#{clause})"
146
147
  end
147
148
 
148
149
  def _add_rule(what, condition)
@@ -14,6 +14,29 @@ module Acl9
14
14
  generator.acl_block!(&block)
15
15
  generator.install_on(self, opts)
16
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 = eval(Acl9.config[:default_subject_method].to_s)
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
+ has_any ? yield(:block) : ''
17
40
  end
18
41
  end
19
42
  end
@@ -1,5 +1,5 @@
1
- require File.join(File.dirname(__FILE__), 'model_extensions', 'subject')
2
- require File.join(File.dirname(__FILE__), 'model_extensions', 'object')
1
+ require File.join(File.dirname(__FILE__), 'model_extensions', 'for_subject')
2
+ require File.join(File.dirname(__FILE__), 'model_extensions', 'for_object')
3
3
 
4
4
  module Acl9
5
5
  module ModelExtensions #:nodoc:
@@ -16,6 +16,8 @@ module Acl9
16
16
  # Class name of the role class (e.g. 'AccountRole')
17
17
  # @option options [String] :join_table_name (Acl9::config[:default_join_table_name])
18
18
  # Join table name (e.g. 'accounts_account_roles')
19
+ # @option options [String] :association_name (Acl9::config[:default_association_name])
20
+ # Association name (e.g. ':roles')
19
21
  # @example
20
22
  # class User < ActiveRecord::Base
21
23
  # acts_as_authorization_subject
@@ -31,17 +33,21 @@ module Acl9
31
33
  # @see Acl9::ModelExtensions::Subject
32
34
  #
33
35
  def acts_as_authorization_subject(options = {})
36
+ assoc = options[:association_name] || Acl9::config[:default_association_name]
34
37
  role = options[:role_class_name] || Acl9::config[:default_role_class_name]
35
38
  join_table = options[:join_table_name] || Acl9::config[:default_join_table_name] ||
36
39
  join_table_name(undecorated_table_name(self.to_s), undecorated_table_name(role))
37
40
 
38
- has_and_belongs_to_many :role_objects, :class_name => role, :join_table => join_table
41
+ has_and_belongs_to_many assoc, :class_name => role, :join_table => join_table
42
+
43
+ cattr_accessor :_auth_role_class_name, :_auth_subject_class_name,
44
+ :_auth_role_assoc_name
39
45
 
40
- cattr_accessor :_auth_role_class_name, :_auth_subject_class_name
41
46
  self._auth_role_class_name = role
42
47
  self._auth_subject_class_name = self.to_s
48
+ self._auth_role_assoc_name = assoc
43
49
 
44
- include Acl9::ModelExtensions::Subject
50
+ include Acl9::ModelExtensions::ForSubject
45
51
  end
46
52
 
47
53
  # Add role query and set methods to the class (making it an auth object class).
@@ -81,7 +87,7 @@ module Acl9
81
87
 
82
88
  sql_where = <<-'EOS'
83
89
  WHERE authorizable_type = '#{self.class.base_class.to_s}'
84
- AND authorizable_id = #{id}
90
+ AND authorizable_id = #{column_for_attribute(self.class.primary_key).text? ? "'#{id}'": id}
85
91
  EOS
86
92
 
87
93
  has_many :accepted_roles, :as => :authorizable, :class_name => role, :dependent => :destroy
@@ -91,7 +97,7 @@ module Acl9
91
97
  :counter_sql => ("SELECT COUNT(DISTINCT #{subj_table}.id)" + sql_tables + sql_where),
92
98
  :readonly => true
93
99
 
94
- include Acl9::ModelExtensions::Object
100
+ include Acl9::ModelExtensions::ForObject
95
101
  end
96
102
 
97
103
  # Make a class an auth role class.
@@ -1,6 +1,6 @@
1
1
  module Acl9
2
2
  module ModelExtensions
3
- module Object
3
+ module ForObject
4
4
  ##
5
5
  # Role check.
6
6
  #
@@ -1,6 +1,6 @@
1
1
  module Acl9
2
2
  module ModelExtensions
3
- module Subject
3
+ module ForSubject
4
4
  ##
5
5
  # Role check.
6
6
  #
@@ -164,12 +164,21 @@ module Acl9
164
164
  role.destroy if role.send(self._auth_subject_class_name.demodulize.tableize).empty?
165
165
  end
166
166
  end
167
-
167
+
168
168
  protected
169
169
 
170
170
  def _auth_role_class
171
171
  self.class._auth_role_class_name.constantize
172
172
  end
173
+
174
+ def _auth_role_assoc
175
+ self.class._auth_role_assoc_name
176
+ end
177
+
178
+ def role_objects
179
+ send(self._auth_role_assoc)
180
+ end
181
+
173
182
  end
174
183
  end
175
184
  end
@@ -753,6 +753,43 @@ class DslBaseTest < Test::Unit::TestCase
753
753
  permit_some(list, @user2, %w(show index delete destroy))
754
754
  permit_some(list, @user3, %w(show index delete destroy), :object => @foo)
755
755
  end
756
+
757
+ it "should work with anonymous" do
758
+ @user << :superadmin
759
+
760
+ list = acl do
761
+ allow :superadmin
762
+
763
+ action :index, :show do
764
+ allow anonymous
765
+ end
766
+ end
767
+
768
+ @all_actions = %w(show index edit update delete destroy)
769
+
770
+ permit_some(list, @user, @all_actions)
771
+ permit_some(list, nil, %w(index show))
772
+ end
773
+
774
+ it "should work with anonymous and other role inside" do
775
+ @user << :superadmin
776
+ @user2 << :member
777
+
778
+ list = acl do
779
+ allow :superadmin
780
+
781
+ action :index, :show do
782
+ allow anonymous
783
+ allow :member
784
+ end
785
+ end
786
+
787
+ @all_actions = %w(show index edit update delete destroy)
788
+
789
+ permit_some(list, @user, @all_actions)
790
+ permit_some(list, @user2, %w(index show))
791
+ permit_some(list, nil, %w(index show))
792
+ end
756
793
  end
757
794
  end
758
795
 
@@ -17,8 +17,12 @@ class HelperTest < Test::Unit::TestCase
17
17
  user = Object.new
18
18
 
19
19
  class <<user
20
- def has_role?(role, obj=nil)
21
- role == 'hamlet'
20
+ def has_role?(role, object=nil)
21
+ if object
22
+ return (role == 'hamlet' && object.name == 'castle')
23
+ else
24
+ return role == 'hamlet'
25
+ end
22
26
  end
23
27
  end
24
28
 
@@ -29,7 +33,7 @@ class HelperTest < Test::Unit::TestCase
29
33
  module NotLoggedIn
30
34
  def current_user; nil end
31
35
  end
32
-
36
+
33
37
  module Noone
34
38
  def current_user
35
39
  user = Object.new
@@ -54,11 +58,11 @@ class HelperTest < Test::Unit::TestCase
54
58
  class Klass1 < Base
55
59
  include Hamlet
56
60
  end
57
-
61
+
58
62
  class Klass2 < Base
59
63
  include NotLoggedIn
60
64
  end
61
-
65
+
62
66
  class Klass3 < Base
63
67
  include Noone
64
68
  end
@@ -66,28 +70,65 @@ class HelperTest < Test::Unit::TestCase
66
70
  it "has :the_question method" do
67
71
  Base.new.should respond_to(:the_question)
68
72
  end
69
-
73
+
70
74
  it "role :hamlet is allowed to be" do
71
75
  k = Klass1.new
72
76
  k.action_name = 'be'
73
77
  k.the_question.should be_true
74
78
  end
75
-
79
+
76
80
  it "role :hamlet is allowed to not_be" do
77
81
  k = Klass1.new
78
82
  k.action_name = 'not_be'
79
83
  k.the_question.should be_true
80
84
  end
81
-
85
+
82
86
  it "not logged in is not allowed to be" do
83
87
  k = Klass2.new
84
88
  k.action_name = 'be'
85
89
  k.the_question.should == false
86
90
  end
87
-
91
+
88
92
  it "noone is not allowed to be" do
89
93
  k = Klass3.new
90
94
  k.action_name = 'be'
91
95
  k.the_question.should == false
92
96
  end
97
+
98
+ it "has :show_to method" do
99
+ Base.new.should respond_to(:show_to)
100
+ end
101
+
102
+ it "has :show_to hamlet 'hello hamlet' message" do
103
+ k = Klass1.new
104
+ message = 'hello hamlet'
105
+ k.show_to('hamlet') { message }.should == message
106
+ end
107
+
108
+ it "has to show message if user has hamlet role on object" do
109
+ k = Klass1.new
110
+ message = 'hello hamlet'
111
+
112
+ obj = Object.new
113
+ def obj.name; 'castle'; end
114
+
115
+ k.show_to('hamlet', :of => obj) { message }.should == message
116
+ end
117
+
118
+ it "has not to show message if user has no hamlet role on object" do
119
+ k = Klass1.new
120
+
121
+ obj = Object.new
122
+ def obj.name; 'persia'; end
123
+
124
+ k.show_to('hamlet', :of => obj) { 'hello my prince' }.should == ''
125
+ end
126
+
127
+ it "has :show_to nothing to NotLoggedIn" do
128
+ k = Klass2.new
129
+ k.action_name = 'be'
130
+ message = 'hello hamlet'
131
+ k.show_to(:hamlet) { message }.should == ''
132
+ end
133
+
93
134
  end
@@ -14,6 +14,10 @@ class RolesTest < Test::Unit::TestCase
14
14
  @user2 = User.create!
15
15
  @foo = Foo.create!
16
16
  @bar = Bar.create!
17
+ #create authorized object that has a string primary key
18
+ @uuid = Uuid.new
19
+ @uuid.uuid = "C41642EE-2780-0001-189F-17F3101B26E0"
20
+ @uuid.save
17
21
  end
18
22
 
19
23
  it "should not have any roles by default" do
@@ -221,6 +225,20 @@ class RolesTest < Test::Unit::TestCase
221
225
  Role.count.should == 0
222
226
  end
223
227
 
228
+ it "should be able to get users that have a role on a authorized object" do
229
+ @user.has_role!('owner', @bar)
230
+ @user2.has_role!('owner', @bar)
231
+
232
+ @bar.users.count.should == 2
233
+ end
234
+
235
+ it "should be able to get users that have a role on a authorized object with text primary key" do
236
+ @user.has_role!('owner', @uuid)
237
+ @user2.has_role!('owner', @uuid)
238
+
239
+ @uuid.users.count.should == 2
240
+ end
241
+
224
242
  it "should accept :symbols as role names" do
225
243
  @user.has_role! :admin
226
244
  @user.has_role! :_3133t
@@ -278,6 +296,33 @@ class RolesWithCustomClassNamesTest < Test::Unit::TestCase
278
296
  end
279
297
  end
280
298
 
299
+ class RolesWithCustomAssociationNamesTest < Test::Unit::TestCase
300
+ before do
301
+ DifferentAssociationNameRole.destroy_all
302
+ [DifferentAssociationNameSubject, FooBar].each { |model| model.delete_all }
303
+
304
+ @subj = DifferentAssociationNameSubject.create!
305
+ @subj2 = DifferentAssociationNameSubject.create!
306
+ @foobar = FooBar.create!
307
+ end
308
+
309
+ it "should basically work" do
310
+ lambda do
311
+ @subj.has_role!('admin')
312
+ @subj.has_role!('user', @foobar)
313
+ end.should change { DifferentAssociationNameRole.count }.from(0).to(2)
314
+
315
+ @subj.has_role?('admin').should be_true
316
+ @subj2.has_role?('admin').should be_false
317
+
318
+ @subj.has_role?(:user, @foobar).should be_true
319
+ @subj2.has_role?(:user, @foobar).should be_false
320
+
321
+ @subj.has_no_roles!
322
+ @subj2.has_no_roles!
323
+ end
324
+ end
325
+
281
326
  class UsersRolesAndSubjectsWithNamespacedClassNamesTest < Test::Unit::TestCase
282
327
  before do
283
328
  Other::Role.destroy_all
@@ -10,6 +10,11 @@ class Foo < ActiveRecord::Base
10
10
  acts_as_authorization_object
11
11
  end
12
12
 
13
+ class Uuid < ActiveRecord::Base
14
+ set_primary_key "uuid"
15
+ acts_as_authorization_object
16
+ end
17
+
13
18
  class Bar < ActiveRecord::Base
14
19
  acts_as_authorization_object
15
20
  end
@@ -26,6 +31,13 @@ class FooBar < ActiveRecord::Base
26
31
  acts_as_authorization_object :role_class_name => 'AnotherRole', :subject_class_name => "AnotherSubject"
27
32
  end
28
33
 
34
+ class DifferentAssociationNameSubject < ActiveRecord::Base
35
+ acts_as_authorization_subject :association_name => 'roles', :role_class_name => "DifferentAssociationNameRole"
36
+ end
37
+
38
+ class DifferentAssociationNameRole < ActiveRecord::Base
39
+ acts_as_authorization_role :subject_class_name => "DifferentAssociationNameSubject"
40
+ end
29
41
 
30
42
  module Other
31
43
 
@@ -44,4 +56,4 @@ module Other
44
56
  acts_as_authorization_object :role_class_name => 'Other::Role', :subject_class_name => "Other::User"
45
57
  end
46
58
 
47
- end
59
+ end
@@ -2,7 +2,7 @@ ActiveRecord::Schema.define(:version => 0) do
2
2
  create_table "roles", :force => true do |t|
3
3
  t.string "name", :limit => 40
4
4
  t.string "authorizable_type", :limit => 40
5
- t.integer "authorizable_id"
5
+ t.string "authorizable_id"
6
6
  t.datetime "created_at"
7
7
  t.datetime "updated_at"
8
8
  end
@@ -15,8 +15,17 @@ ActiveRecord::Schema.define(:version => 0) do
15
15
  t.datetime "updated_at"
16
16
  end
17
17
 
18
+ create_table "different_association_name_roles", :force => true do |t|
19
+ t.string "name", :limit => 40
20
+ t.string "authorizable_type", :limit => 40
21
+ t.integer "authorizable_id"
22
+ t.datetime "created_at"
23
+ t.datetime "updated_at"
24
+ end
25
+
18
26
  create_table "users", :force => true do |t| end
19
27
  create_table "another_subjects", :force => true do |t| end
28
+ create_table "different_association_name_subjects", :force => true do |t| end
20
29
 
21
30
  create_table "roles_users", :id => false, :force => true do |t|
22
31
  t.integer "user_id"
@@ -31,11 +40,25 @@ ActiveRecord::Schema.define(:version => 0) do
31
40
  t.datetime "created_at"
32
41
  t.datetime "updated_at"
33
42
  end
43
+
44
+ create_table "different_association_name_roles_different_association_name_subjects", :id => false, :force => true do |t|
45
+ t.integer "different_association_name_subject_id"
46
+ t.integer "different_association_name_role_id"
47
+ t.datetime "created_at"
48
+ t.datetime "updated_at"
49
+ end
50
+
34
51
  create_table "foos", :force => true do |t|
35
52
  t.datetime "created_at"
36
53
  t.datetime "updated_at"
37
54
  end
38
55
 
56
+ create_table "uuids", :id => false, :force => true do |t|
57
+ t.string "uuid"
58
+ t.datetime "created_at"
59
+ t.datetime "updated_at"
60
+ end
61
+
39
62
  create_table "bars", :force => true do |t|
40
63
  t.datetime "created_at"
41
64
  t.datetime "updated_at"
@@ -17,7 +17,7 @@ class Test::Unit::TestCase
17
17
  custom_matcher :be_false do |receiver, matcher, args|
18
18
  !receiver
19
19
  end
20
-
20
+
21
21
  custom_matcher :be_true do |receiver, matcher, args|
22
22
  !!receiver
23
23
  end
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: 0.11.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - oleg dashevskii
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-10-10 00:00:00 +07:00
12
+ date: 2010-01-04 00:00:00 +06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -40,6 +40,7 @@ extensions: []
40
40
 
41
41
  extra_rdoc_files:
42
42
  - README.textile
43
+ - TODO
43
44
  files:
44
45
  - CHANGELOG.textile
45
46
  - MIT-LICENSE
@@ -54,8 +55,8 @@ files:
54
55
  - lib/acl9/controller_extensions/generators.rb
55
56
  - lib/acl9/helpers.rb
56
57
  - lib/acl9/model_extensions.rb
57
- - lib/acl9/model_extensions/object.rb
58
- - lib/acl9/model_extensions/subject.rb
58
+ - lib/acl9/model_extensions/for_object.rb
59
+ - lib/acl9/model_extensions/for_subject.rb
59
60
  - test/access_control_test.rb
60
61
  - test/dsl_base_test.rb
61
62
  - test/helpers_test.rb