zuul 0.1.1 → 0.2.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 (80) hide show
  1. data/lib/generators/zuul/orm_helpers.rb +21 -0
  2. data/lib/generators/zuul/permission_generator.rb +57 -0
  3. data/lib/generators/zuul/permission_role_generator.rb +40 -0
  4. data/lib/generators/zuul/permission_subject_generator.rb +40 -0
  5. data/lib/generators/zuul/role_generator.rb +58 -0
  6. data/lib/generators/zuul/role_subject_generator.rb +40 -0
  7. data/lib/generators/zuul/subject_generator.rb +39 -0
  8. data/lib/generators/zuul/templates/permission.rb +18 -0
  9. data/lib/generators/zuul/templates/permission_existing.rb +25 -0
  10. data/lib/generators/zuul/templates/permission_role.rb +17 -0
  11. data/lib/generators/zuul/templates/permission_role_existing.rb +24 -0
  12. data/lib/generators/zuul/templates/permission_subject.rb +17 -0
  13. data/lib/generators/zuul/templates/permission_subject_existing.rb +24 -0
  14. data/lib/generators/zuul/templates/role.rb +20 -0
  15. data/lib/generators/zuul/templates/role_existing.rb +27 -0
  16. data/lib/generators/zuul/templates/role_subject.rb +17 -0
  17. data/lib/generators/zuul/templates/role_subject_existing.rb +24 -0
  18. data/lib/tasks/zuul.rake +56 -0
  19. data/lib/zuul.rb +14 -5
  20. data/lib/zuul/action_controller.rb +108 -0
  21. data/lib/zuul/action_controller/dsl.rb +384 -0
  22. data/lib/zuul/action_controller/evaluators.rb +60 -0
  23. data/lib/zuul/active_record.rb +338 -0
  24. data/lib/zuul/active_record/context.rb +38 -0
  25. data/lib/zuul/active_record/permission.rb +31 -0
  26. data/lib/zuul/active_record/permission_role.rb +29 -0
  27. data/lib/zuul/active_record/permission_subject.rb +29 -0
  28. data/lib/zuul/active_record/role.rb +117 -0
  29. data/lib/zuul/active_record/role_subject.rb +29 -0
  30. data/lib/zuul/active_record/scope.rb +71 -0
  31. data/lib/zuul/active_record/subject.rb +239 -0
  32. data/lib/zuul/configuration.rb +149 -0
  33. data/lib/zuul/context.rb +53 -0
  34. data/lib/zuul/exceptions.rb +3 -0
  35. data/lib/zuul/exceptions/access_denied.rb +9 -0
  36. data/lib/zuul/exceptions/invalid_context.rb +9 -0
  37. data/lib/zuul/exceptions/undefined_scope.rb +9 -0
  38. data/lib/zuul/railtie.rb +5 -0
  39. data/lib/zuul/version.rb +3 -0
  40. data/lib/zuul_viz.rb +195 -0
  41. data/spec/db/schema.rb +172 -0
  42. data/spec/spec_helper.rb +25 -0
  43. data/spec/support/capture_stdout.rb +12 -0
  44. data/spec/support/models.rb +167 -0
  45. data/spec/zuul/active_record/context_spec.rb +55 -0
  46. data/spec/zuul/active_record/permission_role_spec.rb +84 -0
  47. data/spec/zuul/active_record/permission_spec.rb +174 -0
  48. data/spec/zuul/active_record/permission_subject_spec.rb +84 -0
  49. data/spec/zuul/active_record/role_spec.rb +694 -0
  50. data/spec/zuul/active_record/role_subject_spec.rb +84 -0
  51. data/spec/zuul/active_record/scope_spec.rb +75 -0
  52. data/spec/zuul/active_record/subject_spec.rb +1186 -0
  53. data/spec/zuul/active_record_spec.rb +624 -0
  54. data/spec/zuul/configuration_spec.rb +254 -0
  55. data/spec/zuul/context_spec.rb +128 -0
  56. data/spec/zuul_spec.rb +15 -0
  57. metadata +181 -70
  58. data/.document +0 -5
  59. data/.gitignore +0 -23
  60. data/LICENSE +0 -20
  61. data/README.rdoc +0 -65
  62. data/Rakefile +0 -54
  63. data/VERSION +0 -1
  64. data/lib/zuul/restrict_access.rb +0 -104
  65. data/lib/zuul/valid_roles.rb +0 -37
  66. data/spec/rails_root/app/controllers/application_controller.rb +0 -2
  67. data/spec/rails_root/app/models/user.rb +0 -8
  68. data/spec/rails_root/config/boot.rb +0 -110
  69. data/spec/rails_root/config/database.yml +0 -5
  70. data/spec/rails_root/config/environment.rb +0 -7
  71. data/spec/rails_root/config/environments/test.rb +0 -7
  72. data/spec/rails_root/config/initializers/session_store.rb +0 -15
  73. data/spec/rails_root/config/routes.rb +0 -4
  74. data/spec/rails_root/db/test.sqlite3 +0 -0
  75. data/spec/rails_root/log/test.log +0 -5388
  76. data/spec/rails_root/spec/controllers/require_user_spec.rb +0 -138
  77. data/spec/rails_root/spec/controllers/restrict_access_spec.rb +0 -64
  78. data/spec/rails_root/spec/models/user_spec.rb +0 -37
  79. data/spec/rails_root/spec/spec_helper.rb +0 -34
  80. data/zuul.gemspec +0 -78
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Zuul::ActiveRecord::RoleSubject" do
4
+ before(:each) do
5
+ Role.acts_as_authorization_role
6
+ end
7
+
8
+ describe "accessible attributes" do
9
+ it "should allow mass assignment of role class foreign key" do
10
+ ru = RoleUser.new(:role_id => 1)
11
+ ru.role_id.should == 1
12
+ end
13
+
14
+ it "should allow mass assignment of subject class foreign key" do
15
+ ru = RoleUser.new(:user_id => 1)
16
+ ru.user_id.should == 1
17
+ end
18
+
19
+ it "should allow mass assignment of :context" do
20
+ context = Context.create(:name => "Test Context")
21
+ ru = RoleUser.new(:context => context)
22
+ ru.context_type.should == 'Context'
23
+ ru.context_id.should == context.id
24
+ end
25
+
26
+ it "should allow mass assignment of :context_type" do
27
+ ru = RoleUser.new(:context_type => 'Context')
28
+ ru.context_type.should == 'Context'
29
+ end
30
+
31
+ it "should allow mass assignment of :context_id" do
32
+ ru = RoleUser.new(:context_id => 1)
33
+ ru.context_id.should == 1
34
+ end
35
+ end
36
+
37
+ context "validations for core role fields" do
38
+ it "should validate presence of role class foreign key" do
39
+ ru = RoleUser.new()
40
+ ru.valid?.should be_false
41
+ ru.errors.keys.should include(:role_id)
42
+ end
43
+
44
+ it "should validate presence of subject class foreign key" do
45
+ ru = RoleUser.new()
46
+ ru.valid?.should be_false
47
+ ru.errors.keys.should include(:user_id)
48
+ end
49
+
50
+ it "should validate uniqueness of role class foreign key scoped to context_type, context_id and the subject class foreign key" do
51
+ RoleUser.create(:role_id => 1, :user_id => 1)
52
+ ru = RoleUser.create(:role_id => 1, :user_id => 1)
53
+ ru.valid?.should be_false
54
+ ru.errors.keys.should include(:role_id)
55
+
56
+ RoleUser.create(:role_id => 1, :user_id => 1, :context_type => 'Context').valid?.should be_true
57
+ ru = RoleUser.create(:role_id => 1, :user_id => 1, :context_type => 'Context')
58
+ ru.valid?.should be_false
59
+ ru.errors.keys.should include(:role_id)
60
+
61
+ RoleUser.create(:role_id => 1, :user_id => 1, :context_type => 'Context', :context_id => 1).valid?.should be_true
62
+ ru = RoleUser.create(:role_id => 1, :user_id => 1, :context_type => 'Context', :context_id => 1)
63
+ ru.valid?.should be_false
64
+ ru.errors.keys.should include(:role_id)
65
+ end
66
+
67
+ it "should validate numericality of role class foreign key with integers only" do
68
+ ru = RoleUser.new(:role_id => 'a', :user_id => 1)
69
+ ru.valid?.should be_false
70
+ ru.errors.keys.should include(:role_id)
71
+ ru.role_id = 1.3
72
+ ru.valid?.should be_false
73
+ ru.errors.keys.should include(:role_id)
74
+ end
75
+ end
76
+
77
+ it "should provide the model with belongs_to associations for roles and subjects" do
78
+ RoleUser.reflections.keys.should include(:role)
79
+ RoleUser.reflections.keys.should include(:user)
80
+ ru = RoleUser.create(:role_id => 1, :use_id => 1)
81
+ ru.should respond_to(:role)
82
+ ru.should respond_to(:user)
83
+ end
84
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Zuul::ActiveRecord::Scope" do
4
+ it "should require an auth config to be initialized" do
5
+ scope = Zuul::ActiveRecord::Scope.new(Zuul::Configuration.new)
6
+ scope.should be_an_instance_of(Zuul::ActiveRecord::Scope)
7
+ end
8
+
9
+ context "class reflections" do
10
+ before(:each) do
11
+ @scope = Zuul::ActiveRecord::Scope.new(Zuul::Configuration.new)
12
+ end
13
+
14
+ context "class type methods" do
15
+ it "should define *_class_name methods for each of the class types" do
16
+ Zuul::Configuration::DEFAULT_AUTHORIZATION_CLASSES.keys.each do |class_type|
17
+ @scope.should respond_to("#{class_type.to_s.gsub(/_class$/,'').singularize}_class_name")
18
+ end
19
+ end
20
+
21
+ it "should define *_class methods for each of the class types" do
22
+ Zuul::Configuration::DEFAULT_AUTHORIZATION_CLASSES.keys.each do |class_type|
23
+ @scope.should respond_to("#{class_type.to_s.gsub(/_class$/,'').singularize}_class")
24
+ end
25
+ end
26
+
27
+ it "should define *_table_name methods for each of the class types" do
28
+ Zuul::Configuration::DEFAULT_AUTHORIZATION_CLASSES.keys.each do |class_type|
29
+ @scope.should respond_to("#{class_type.to_s.gsub(/_class$/,'').singularize}_table_name")
30
+ end
31
+ end
32
+
33
+ it "should define *_foreign_key methods for each of the primary class types" do
34
+ Zuul::Configuration::PRIMARY_AUTHORIZATION_CLASSES.keys.each do |class_type|
35
+ @scope.should respond_to("#{class_type.to_s.gsub(/_class$/,'').singularize}_foreign_key")
36
+ end
37
+ end
38
+
39
+ it "should alias pluralized versions of each method" do
40
+ Zuul::Configuration::DEFAULT_AUTHORIZATION_CLASSES.keys.each do |class_type|
41
+ @scope.should respond_to("#{class_type.to_s.gsub(/_class$/,'').pluralize}_class_name")
42
+ @scope.should respond_to("#{class_type.to_s.gsub(/_class$/,'').pluralize}_class")
43
+ @scope.should respond_to("#{class_type.to_s.gsub(/_class$/,'').pluralize}_table_name")
44
+ end
45
+ Zuul::Configuration::PRIMARY_AUTHORIZATION_CLASSES.keys.each do |class_type|
46
+ @scope.should respond_to("#{class_type.to_s.gsub(/_class$/,'').pluralize}_foreign_key")
47
+ end
48
+ end
49
+ end
50
+
51
+ context "class name methods" do
52
+ it "should alias class name methods to the class type equivalent" do
53
+ Zuul::Configuration::DEFAULT_AUTHORIZATION_CLASSES.keys.each do |class_type|
54
+ @scope.should respond_to("#{@scope.config.send(class_type).to_s.singularize}_class_name")
55
+ @scope.should respond_to("#{@scope.config.send(class_type).to_s.singularize}_class")
56
+ @scope.should respond_to("#{@scope.config.send(class_type).to_s.singularize}_table_name")
57
+ end
58
+ Zuul::Configuration::PRIMARY_AUTHORIZATION_CLASSES.keys.each do |class_type|
59
+ @scope.should respond_to("#{@scope.config.send(class_type).to_s.singularize}_foreign_key")
60
+ end
61
+ end
62
+
63
+ it "should alias plurlized versions of each method" do
64
+ Zuul::Configuration::DEFAULT_AUTHORIZATION_CLASSES.keys.each do |class_type|
65
+ @scope.should respond_to("#{@scope.config.send(class_type).to_s.underscore.pluralize}_class_name")
66
+ @scope.should respond_to("#{@scope.config.send(class_type).to_s.underscore.pluralize}_class")
67
+ @scope.should respond_to("#{@scope.config.send(class_type).to_s.underscore.pluralize}_table_name")
68
+ end
69
+ Zuul::Configuration::PRIMARY_AUTHORIZATION_CLASSES.keys.each do |class_type|
70
+ @scope.should respond_to("#{@scope.config.send(class_type).to_s.underscore.pluralize}_foreign_key")
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,1186 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Zuul::ActiveRecord::Subject" do
4
+ it "should extend the model with RoleMethods" do
5
+ User.acts_as_authorization_subject
6
+ User.ancestors.include?(Zuul::ActiveRecord::Subject::RoleMethods).should == true
7
+ end
8
+
9
+ it "should extend the model with PermissionMethods if permissions are enabled" do
10
+ User.acts_as_authorization_subject
11
+ User.ancestors.include?(Zuul::ActiveRecord::Subject::PermissionMethods).should == true
12
+ end
13
+
14
+ it "should not extend the model with PermissionMethods if permissions are disabled" do
15
+ User.acts_as_authorization_subject :with_permissions => false
16
+ User.ancestors.include?(Zuul::ActiveRecord::Subject::PermissionMethods).should be_false
17
+ end
18
+
19
+ describe "RoleMethods" do
20
+ before(:each) do
21
+ User.acts_as_authorization_subject
22
+ Role.acts_as_authorization_role
23
+ end
24
+
25
+ it "should provide the model with has_many associations for role_subjects and roles" do
26
+ user = User.create(:name => "Test User")
27
+ User.reflections.keys.should include(:role_users)
28
+ User.reflections.keys.should include(:roles)
29
+ user.should respond_to(:role_users)
30
+ user.should respond_to(:roles)
31
+ end
32
+
33
+ it "should use the reflection classes to create the has_many associations" do
34
+ Soldier.acts_as_authorization_subject :role_class => :rank, :with_permissions => false
35
+ Rank.acts_as_authorization_role :subject_class => :soldier, :with_permissions => false
36
+ soldier = Soldier.create(:name => "Test User")
37
+ Soldier.reflections.keys.should include(:rank_soldiers)
38
+ Soldier.reflections.keys.should include(:ranks)
39
+ soldier.should respond_to(:rank_soldiers)
40
+ soldier.should respond_to(:ranks)
41
+ end
42
+
43
+ describe "assign_role" do
44
+ before(:each) do
45
+ @user = User.create(:name => "Test User")
46
+ end
47
+
48
+ it "should require a role object or slug" do
49
+ expect { @user.assign_role }.to raise_exception
50
+ end
51
+
52
+ it "should accept an optional context" do
53
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
54
+ expect { @user.assign_role(:admin, nil) }.to_not raise_exception
55
+ end
56
+
57
+ it "should use nil context when none is provided" do
58
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
59
+ role_user = @user.assign_role(:admin)
60
+ role_user.id.should_not be_nil
61
+ role_user.context_type.should be_nil
62
+ end
63
+
64
+ it "should use the context when one is provided" do
65
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
66
+ context = Context.create(:name => "Test Context")
67
+
68
+ class_role_user = @user.assign_role(role, Context)
69
+ class_role_user.id.should_not be_nil
70
+ class_role_user.context_type.should == 'Context'
71
+ class_role_user.context_id.should be_nil
72
+
73
+ inst_role_user = @user.assign_role(role, context)
74
+ inst_role_user.id.should_not be_nil
75
+ inst_role_user.context_type.should == 'Context'
76
+ inst_role_user.context_id.should == context.id
77
+ end
78
+
79
+ it "should use target_role to lookup the closest contextual match when a role slug is provided" do
80
+ context = Context.create(:name => "Test Context")
81
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
82
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
83
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
84
+
85
+ nil_role_user = @user.assign_role(:admin, nil)
86
+ nil_role_user.id.should_not be_nil
87
+ nil_role_user.context_type.should be_nil
88
+ nil_role_user.context_id.should be_nil
89
+ nil_role_user.role.id.should == nil_role.id
90
+
91
+ class_role_user = @user.assign_role(:admin, Context)
92
+ class_role_user.id.should_not be_nil
93
+ class_role_user.context_type.should == 'Context'
94
+ class_role_user.context_id.should be_nil
95
+ class_role_user.role.id.should == class_role.id
96
+
97
+ inst_role_user = @user.assign_role(:admin, context)
98
+ inst_role_user.id.should_not be_nil
99
+ inst_role_user.context_type.should == 'Context'
100
+ inst_role_user.context_id.should == context.id
101
+ inst_role_user.role.id.should == inst_role.id
102
+ end
103
+
104
+ it "should use the role object when one is provided" do
105
+ context = Context.create(:name => "Test Context")
106
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
107
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
108
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
109
+
110
+ class_role_user = @user.assign_role(nil_role, Context)
111
+ class_role_user.id.should_not be_nil
112
+ class_role_user.context_type.should == 'Context'
113
+ class_role_user.context_id.should be_nil
114
+ class_role_user.role.id.should == nil_role.id
115
+
116
+ inst_role_user = @user.assign_role(nil_role, context)
117
+ inst_role_user.id.should_not be_nil
118
+ inst_role_user.context_type.should == 'Context'
119
+ inst_role_user.context_id.should == context.id
120
+ inst_role_user.role.id.should == nil_role.id
121
+ end
122
+
123
+ it "should fail and return false if the provided role is nil" do
124
+ @user.assign_role(nil).should be_false
125
+ @user.assign_role(nil, Context).should be_false
126
+ end
127
+
128
+ it "should fail and return false if the provided role cannot be used within the provided context" do
129
+ context = Context.create(:name => "Test Context")
130
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
131
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
132
+
133
+ @user.assign_role(class_role, nil).should be_false
134
+ @user.assign_role(inst_role, nil).should be_false
135
+ @user.assign_role(inst_role, Context).should be_false
136
+ end
137
+
138
+ it "should create the role_subjects record to link the subject to the provided role" do
139
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
140
+ @user.assign_role(role)
141
+ RoleUser.where(:user_id => @user.id, :role_id => role.id).count.should == 1
142
+ end
143
+
144
+ it "should fail and return false if the provided role is already assigned in the provided context" do
145
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
146
+ context = Context.create(:name => "Test Context")
147
+ @user.assign_role(role)
148
+ @user.assign_role(role).should be_false
149
+ @user.assign_role(role, Context)
150
+ @user.assign_role(role, Context).should be_false
151
+ @user.assign_role(role, context)
152
+ @user.assign_role(role, context).should be_false
153
+ end
154
+
155
+ context "when forcing context" do
156
+ it "should not go up the context chain to find the role when a role slug is provided" do
157
+ context = Context.create(:name => "Test Context")
158
+
159
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
160
+ nil_role_user = @user.assign_role(:admin, nil, true)
161
+ nil_role_user.id.should_not be_nil
162
+ nil_role_user.context_type.should be_nil
163
+ nil_role_user.context_id.should be_nil
164
+ nil_role_user.role.id.should == nil_role.id
165
+
166
+ @user.assign_role(:admin, Context, true).should be_false
167
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
168
+ class_role_user = @user.assign_role(:admin, Context, true)
169
+ class_role_user.id.should_not be_nil
170
+ class_role_user.context_type.should == 'Context'
171
+ class_role_user.context_id.should be_nil
172
+ class_role_user.role.id.should == class_role.id
173
+
174
+ @user.assign_role(:admin, context, true).should be_false
175
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
176
+ inst_role_user = @user.assign_role(:admin, context, true)
177
+ inst_role_user.id.should_not be_nil
178
+ inst_role_user.context_type.should == 'Context'
179
+ inst_role_user.context_id.should == context.id
180
+ inst_role_user.role.id.should == inst_role.id
181
+ end
182
+ end
183
+ end
184
+
185
+ describe "unassign_role" do
186
+ before(:each) do
187
+ @user = User.create(:name => "Test User")
188
+ end
189
+
190
+ it "should require a role object or slug" do
191
+ expect { @user.unassign_role }.to raise_exception
192
+ end
193
+
194
+ it "should accept an optional context" do
195
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
196
+ expect { @user.unassign_role(:admin, nil) }.to_not raise_exception
197
+ end
198
+
199
+ it "should use nil context when none is provided" do
200
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
201
+ @user.assign_role(:admin, nil)
202
+ @user.assign_role(:admin, Context)
203
+
204
+ unassigned = @user.unassign_role(:admin)
205
+ unassigned.should be_an_instance_of(RoleUser)
206
+ roles = RoleUser.where(:user_id => @user.id, :role_id => role.id)
207
+ roles.length.should == 1
208
+ roles[0].context_type.should == 'Context'
209
+ end
210
+
211
+ it "should use target_role to lookup the closest contextual match when a role slug is provided" do
212
+ context = Context.create(:name => "Test Context")
213
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
214
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
215
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
216
+ @user.assign_role(nil_role, nil)
217
+ @user.assign_role(class_role, Context)
218
+ @user.assign_role(nil_role, Context)
219
+ @user.assign_role(inst_role, context)
220
+ @user.assign_role(class_role, context)
221
+
222
+ @user.unassign_role(:admin, context).role_id.should == inst_role.id
223
+ @user.unassign_role(:admin, context).should be_false
224
+ @user.unassign_role(:admin, Context).role_id.should == class_role.id
225
+ @user.unassign_role(:admin, Context).should be_false
226
+ end
227
+
228
+ it "should use the role object when one is provided" do
229
+ context = Context.create(:name => "Test Context")
230
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
231
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
232
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
233
+ @user.assign_role(nil_role, nil)
234
+ @user.assign_role(class_role, Context)
235
+ @user.assign_role(nil_role, Context)
236
+ @user.assign_role(inst_role, context)
237
+ @user.assign_role(class_role, context)
238
+
239
+ @user.unassign_role(class_role, context).role_id.should == class_role.id
240
+ @user.unassign_role(inst_role, context).role_id.should == inst_role.id
241
+ @user.unassign_role(nil_role, Context).role_id.should == nil_role.id
242
+ @user.unassign_role(class_role, Context).role_id.should == class_role.id
243
+ end
244
+
245
+ it "should fail and return false if the provided role is nil" do
246
+ @user.unassign_role(nil).should be_false
247
+ @user.unassign_role(nil, Context).should be_false
248
+ end
249
+
250
+ it "should remove the role_subjects record that links the subject to the provided role" do
251
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
252
+ @user.assign_role(role)
253
+ RoleUser.where(:user_id => @user.id, :role_id => role.id).count.should == 1
254
+ @user.unassign_role(role)
255
+ RoleUser.where(:user_id => @user.id, :role_id => role.id).count.should == 0
256
+ end
257
+
258
+ it "should fail and return false if the provided role is not assigned in the provided context" do
259
+ context = Context.create(:name => "Test Context")
260
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
261
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
262
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
263
+ @user.assign_role(nil_role, Context)
264
+ @user.assign_role(class_role, context)
265
+
266
+ @user.unassign_role(inst_role, context).should be_false
267
+ @user.unassign_role(nil_role, nil).should be_false
268
+ @user.unassign_role(class_role, Context).should be_false
269
+ end
270
+
271
+ context "when forcing context" do
272
+ it "should not go up the context chain to find the role when a role slug is provided" do
273
+ context = Context.create(:name => "Test Context")
274
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
275
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
276
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
277
+ @user.assign_role(nil_role, nil)
278
+ @user.assign_role(class_role, Context)
279
+ @user.assign_role(nil_role, Context)
280
+ @user.assign_role(inst_role, context)
281
+ @user.assign_role(class_role, context)
282
+
283
+ @user.unassign_role(:admin, context, true).role_id.should == inst_role.id
284
+ inst_role.destroy
285
+ @user.unassign_role(:admin, context, true).should be_false
286
+ @user.unassign_role(:admin, Context, true).role_id.should == class_role.id
287
+ class_role.destroy
288
+ @user.unassign_role(:admin, Context, true).should be_false
289
+ end
290
+ end
291
+ end
292
+
293
+ describe "has_role?" do
294
+ before(:each) do
295
+ @user = User.create(:name => "Test User")
296
+ end
297
+
298
+ it "should require a role object or slug" do
299
+ expect { @user.has_role? }.to raise_exception
300
+ end
301
+
302
+ it "should accept an optional context" do
303
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
304
+ expect { @user.has_role?(:admin, nil) }.to_not raise_exception
305
+ end
306
+
307
+ it "should use nil context when none is provided" do
308
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
309
+ @user.assign_role(:admin, Context)
310
+ @user.has_role?(:admin).should be_false
311
+ @user.assign_role(:admin, nil)
312
+ @user.has_role?(:admin).should be_true
313
+ end
314
+
315
+ it "should use target_role to lookup the closest contextual match when a role slug is provided" do
316
+ context = Context.create(:name => "Test Context")
317
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
318
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
319
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
320
+ @user.assign_role(nil_role, Context)
321
+ @user.assign_role(class_role, context)
322
+
323
+ @user.has_role?(:admin, Context).should be_false
324
+ @user.has_role?(:admin, context).should be_false
325
+
326
+ @user.assign_role(class_role, Context)
327
+ @user.assign_role(inst_role, context)
328
+
329
+ @user.has_role?(:admin, Context).should be_true
330
+ @user.has_role?(:admin, context).should be_true
331
+ end
332
+
333
+ it "should use the role object when one is provided" do
334
+ context = Context.create(:name => "Test Context")
335
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
336
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
337
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
338
+ @user.assign_role(nil_role, Context)
339
+ @user.assign_role(class_role, context)
340
+
341
+ @user.has_role?(nil_role, Context).should be_true
342
+ @user.has_role?(class_role, context).should be_true
343
+ @user.has_role?(class_role, Context).should be_false
344
+ @user.has_role?(inst_role, context).should be_false
345
+
346
+ @user.assign_role(class_role, Context)
347
+ @user.assign_role(inst_role, context)
348
+
349
+ @user.has_role?(class_role, Context).should be_true
350
+ @user.has_role?(inst_role, context).should be_true
351
+ end
352
+
353
+ it "should return false if the provided role is nil" do
354
+ @user.has_role?(nil).should be_false
355
+ @user.has_role?(nil, Context).should be_false
356
+ end
357
+
358
+ it "should look up the context chain for the assigned role" do
359
+ context = Context.create(:name => "Test Context")
360
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
361
+ @user.assign_role(role, nil)
362
+ @user.has_role?(:admin, Context).should be_true
363
+ @user.has_role?(:admin, context).should be_true
364
+ @user.unassign_role(role, nil)
365
+ @user.assign_role(role, Context)
366
+ @user.has_role?(:admin, context).should be_true
367
+ end
368
+
369
+ it "should return false if the provided role is not assigned to the subject within the context chain" do
370
+ context = Context.create(:name => "Test Context")
371
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
372
+ @user.has_role?(role, context).should be_false
373
+ @user.has_role?(:admin, Context).should be_false
374
+ @user.has_role?(role, nil).should be_false
375
+
376
+ @user.assign_role(:admin, context)
377
+ @user.has_role?(:admin, context).should_not be_false
378
+ @user.has_role?(role, Context).should be_false
379
+ @user.has_role?(:admin, nil).should be_false
380
+
381
+ @user.assign_role(:admin, Context)
382
+ @user.has_role?(:admin, context).should_not be_false
383
+ @user.has_role?(role, Context).should_not be_false
384
+ @user.has_role?(role, nil).should be_false
385
+ end
386
+
387
+ context "when forcing context" do
388
+ it "should not go up the context chain to find the role when a role slug is provided" do
389
+ context = Context.create(:name => "Test Context")
390
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
391
+ @user.assign_role(nil_role, Context)
392
+ @user.has_role?(:admin, Context, false).should be_true
393
+ @user.has_role?(:admin, Context, true).should be_false
394
+
395
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
396
+ @user.assign_role(class_role, context)
397
+ @user.has_role?(:admin, context, false).should be_true
398
+ @user.has_role?(:admin, context, true).should be_false
399
+ end
400
+ end
401
+ end
402
+
403
+ describe "has_role_or_higher?" do
404
+ before(:each) do
405
+ @user = User.create(:name => "Test User")
406
+ end
407
+
408
+ it "should require a role object or slug" do
409
+ expect { @user.has_role_or_higher? }.to raise_exception
410
+ end
411
+
412
+ it "should accept an optional context" do
413
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
414
+ expect { @user.has_role_or_higher?(:admin, nil) }.to_not raise_exception
415
+ end
416
+
417
+ it "should use nil context when none is provided" do
418
+ admin_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
419
+ mod_role = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80)
420
+ @user.assign_role(:admin, Context)
421
+ @user.has_role_or_higher?(:admin).should be_false
422
+ @user.has_role_or_higher?(:moderator).should be_false
423
+ @user.assign_role(:admin, nil)
424
+ @user.has_role_or_higher?(:admin).should be_true
425
+ @user.has_role_or_higher?(:moderator).should be_true
426
+ end
427
+
428
+ it "should use target_role to lookup the closest contextual match when a role slug is provided" do
429
+ context = Context.create(:name => "Test Context")
430
+ nil_admin = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
431
+ class_admin = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
432
+ inst_admin = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
433
+ nil_mod = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80)
434
+ class_mod = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80, :context_type => 'Context')
435
+ inst_mod = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80, :context_type => 'Context', :context_id => context.id)
436
+ @user.assign_role(nil_admin, Context)
437
+ @user.assign_role(class_admin, context)
438
+
439
+ @user.has_role_or_higher?(:admin, Context).should be_false
440
+ @user.has_role_or_higher?(:moderator, Context).should be_false
441
+ @user.has_role_or_higher?(:admin, context).should be_false
442
+ @user.has_role_or_higher?(:moderator, context).should be_false
443
+
444
+ @user.assign_role(class_admin, Context)
445
+ @user.assign_role(inst_admin, context)
446
+
447
+ @user.has_role_or_higher?(:admin, Context).should be_true
448
+ @user.has_role_or_higher?(:moderator, Context).should be_true
449
+ @user.has_role_or_higher?(:admin, context).should be_true
450
+ @user.has_role_or_higher?(:moderator, context).should be_true
451
+ end
452
+
453
+ it "should use the role object when one is provided" do
454
+ context = Context.create(:name => "Test Context")
455
+ nil_admin = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
456
+ class_admin = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
457
+ inst_admin = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
458
+ nil_mod = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80)
459
+ class_mod = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80, :context_type => 'Context')
460
+ inst_mod = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80, :context_type => 'Context', :context_id => context.id)
461
+ @user.assign_role(nil_admin, Context)
462
+ @user.assign_role(class_admin, context)
463
+
464
+ @user.has_role_or_higher?(nil_admin, Context).should be_true
465
+ @user.has_role_or_higher?(nil_mod, Context).should be_true
466
+ @user.has_role_or_higher?(class_admin, context).should be_true
467
+ @user.has_role_or_higher?(class_mod, context).should be_true
468
+ @user.has_role_or_higher?(class_admin, Context).should be_false
469
+ @user.has_role_or_higher?(class_mod, Context).should be_false
470
+ @user.has_role_or_higher?(inst_admin, context).should be_false
471
+ @user.has_role_or_higher?(inst_mod, context).should be_false
472
+
473
+ @user.assign_role(class_admin, Context)
474
+ @user.assign_role(inst_admin, context)
475
+
476
+ @user.has_role_or_higher?(class_admin, Context).should be_true
477
+ @user.has_role_or_higher?(class_mod, Context).should be_true
478
+ @user.has_role_or_higher?(inst_admin, context).should be_true
479
+ @user.has_role_or_higher?(inst_mod, context).should be_true
480
+ end
481
+
482
+ it "should return false if the provided role is nil" do
483
+ @user.has_role_or_higher?(nil).should be_false
484
+ @user.has_role_or_higher?(nil, Context).should be_false
485
+ end
486
+
487
+ it "should return true if the subject has the provided role via has_role?" do
488
+ context = Context.create(:name => "Test Context")
489
+ admin_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
490
+ mod_role = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80)
491
+ @user.assign_role(admin_role, nil)
492
+ @user.has_role_or_higher?(:admin, nil).should be_true
493
+ end
494
+
495
+ it "should look up the context chain for an assigned role with a level >= that of the provided role" do
496
+ context = Context.create(:name => "Test Context")
497
+ admin_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
498
+ mod_role = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80)
499
+ @user.assign_role(admin_role, nil)
500
+ @user.has_role_or_higher?(:admin, Context).should be_true
501
+ @user.has_role_or_higher?(:moderator, Context).should be_true
502
+ @user.has_role_or_higher?(:admin, context).should be_true
503
+ @user.has_role_or_higher?(:moderator, context).should be_true
504
+ @user.unassign_role(admin_role, nil)
505
+ @user.assign_role(admin_role, Context)
506
+ @user.has_role_or_higher?(:admin, context).should be_true
507
+ @user.has_role_or_higher?(:moderator, context).should be_true
508
+ end
509
+
510
+ it "should return false if a role with a level >= that of the provided role is not assigned to the subject within the context chain" do
511
+ context = Context.create(:name => "Test Context")
512
+ admin_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
513
+ mod_role = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80)
514
+ @user.has_role_or_higher?(admin_role, context).should be_false
515
+ @user.has_role_or_higher?(admin_role, context).should be_false
516
+ @user.has_role_or_higher?(:admin, Context).should be_false
517
+ @user.has_role_or_higher?(:moderator, Context).should be_false
518
+ @user.has_role_or_higher?(admin_role, nil).should be_false
519
+ @user.has_role_or_higher?(mod_role, nil).should be_false
520
+
521
+ @user.assign_role(:admin, context)
522
+ @user.has_role_or_higher?(:admin, context).should_not be_false
523
+ @user.has_role_or_higher?(:moderator, context).should_not be_false
524
+ @user.has_role_or_higher?(admin_role, Context).should be_false
525
+ @user.has_role_or_higher?(mod_role, Context).should be_false
526
+ @user.has_role_or_higher?(:admin, nil).should be_false
527
+ @user.has_role_or_higher?(:moderator, nil).should be_false
528
+
529
+ @user.assign_role(:admin, Context)
530
+ @user.has_role_or_higher?(:admin, context).should_not be_false
531
+ @user.has_role_or_higher?(:moderator, context).should_not be_false
532
+ @user.has_role_or_higher?(admin_role, Context).should_not be_false
533
+ @user.has_role_or_higher?(mod_role, Context).should_not be_false
534
+ @user.has_role_or_higher?(admin_role, nil).should be_false
535
+ @user.has_role_or_higher?(mod_role, nil).should be_false
536
+ end
537
+
538
+ context "when forcing context" do
539
+ it "should not go up the context chain to find the role when a role slug is provided" do
540
+ context = Context.create(:name => "Test Context")
541
+ nil_admin = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
542
+ nil_mod = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80)
543
+ @user.assign_role(nil_admin, Context)
544
+ @user.has_role_or_higher?(:admin, Context, false).should be_true
545
+ @user.has_role_or_higher?(:admin, Context, true).should be_false
546
+ @user.has_role_or_higher?(:moderator, Context, false).should be_true
547
+ @user.has_role_or_higher?(:moderator, Context, true).should be_false
548
+
549
+ class_admin = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
550
+ class_mod = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80, :context_type => 'Context')
551
+ @user.assign_role(class_admin, context)
552
+ @user.has_role_or_higher?(:admin, context, false).should be_true
553
+ @user.has_role_or_higher?(:admin, context, true).should be_false
554
+ @user.has_role_or_higher?(:moderator, context, false).should be_true
555
+ @user.has_role_or_higher?(:moderator, context, true).should be_false
556
+ end
557
+ end
558
+ end
559
+
560
+ describe "highest_role" do
561
+ before(:each) do
562
+ @user = User.create(:name => "Test User")
563
+ end
564
+
565
+ it "should accept an optional context" do
566
+ expect { @user.highest_role(nil) }.to_not raise_exception
567
+ end
568
+
569
+ it "should use nil context when none is provided" do
570
+ admin_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
571
+ @user.assign_role(admin_role, nil)
572
+ @user.highest_role.id.should == admin_role.id
573
+ end
574
+
575
+ it "should return nil if no roles are assigned to the subject within the provided context" do
576
+ admin_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
577
+ @user.highest_role(nil).should be_nil
578
+ @user.highest_role(Context).should be_nil
579
+
580
+ @user.assign_role(admin_role, nil)
581
+
582
+ @user.highest_role(nil).id.should == admin_role.id
583
+ @user.highest_role(Context).id.should == admin_role.id
584
+ end
585
+
586
+ it "should return the role with the highest level that is assigned to the subject within the provided context" do
587
+ admin_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
588
+ mod_role = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80)
589
+ @user.assign_role(admin_role, nil)
590
+ @user.assign_role(mod_role, nil)
591
+ @user.assign_role(mod_role, Context)
592
+ @user.highest_role(nil).id.should == admin_role.id
593
+ @user.highest_role(Context).id.should == admin_role.id
594
+ @user.assign_role(admin_role, Context)
595
+ @user.highest_role(Context).id.should == admin_role.id
596
+ end
597
+
598
+ context "when forcing context" do
599
+ it "should only evaluate roles that match the context exactly" do
600
+ admin_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
601
+ mod_role = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80)
602
+ @user.assign_role(admin_role, nil)
603
+ @user.assign_role(mod_role, nil)
604
+ @user.highest_role(nil).id.should == admin_role.id
605
+ @user.highest_role(Context).id.should == admin_role.id
606
+ @user.highest_role(Context, true).should be_nil
607
+ end
608
+ end
609
+ end
610
+
611
+ describe "roles_for" do
612
+ before(:each) do
613
+ @user = User.create(:name => "Test User")
614
+ end
615
+
616
+ it "should accept an optional context" do
617
+ expect { @user.roles_for(nil) }.to_not raise_exception
618
+ end
619
+
620
+ it "should use nil context when none is provided" do
621
+ admin_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
622
+ @user.assign_role(admin_role, Context)
623
+ @user.roles_for.length.should == 0
624
+ @user.assign_role(admin_role, nil)
625
+ @user.roles_for.length.should == 1
626
+ end
627
+
628
+ it "should return an empty association array if no roles are assigned to the subject within the provided context" do
629
+ context = Context.create(:name => "Test Context")
630
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
631
+ @user.assign_role(role, context)
632
+ @user.roles_for(nil).length.should == 0
633
+ @user.roles_for(Context).length.should == 0
634
+ end
635
+
636
+ it "should return all roles assigned to the subject within the provided context" do
637
+ nil_admin = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
638
+ class_admin = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
639
+ class_mod = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80, :context_type => 'Context')
640
+ @user.assign_role(nil_admin, Context)
641
+ @user.assign_role(class_admin, Context)
642
+ @user.assign_role(class_mod, Context)
643
+ @user.roles_for(Context).length.should == 3
644
+ end
645
+
646
+ context "when forcing context" do
647
+ it "should only return roles that match the context exactly" do
648
+ admin_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
649
+ mod_role = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80)
650
+ @user.assign_role(admin_role, nil)
651
+ @user.assign_role(mod_role, nil)
652
+ @user.roles_for(nil).length.should == 2
653
+ @user.roles_for(Context).length.should == 2
654
+ @user.roles_for(Context, true).length.should == 0
655
+ end
656
+ end
657
+ end
658
+
659
+ describe "roles_for?" do
660
+ before(:each) do
661
+ @user = User.create(:name => "Test User")
662
+ end
663
+
664
+ it "should accept an optional context" do
665
+ expect { @user.roles_for?(nil) }.to_not raise_exception
666
+ end
667
+
668
+ it "should use nil context when none is provided" do
669
+ admin_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
670
+ @user.assign_role(admin_role, Context)
671
+ @user.roles_for?.should be_false
672
+ @user.assign_role(admin_role, nil)
673
+ @user.roles_for?.should be_true
674
+ end
675
+
676
+ it "should return false if no roles are assigned to the subject within the provided context" do
677
+ context = Context.create(:name => "Test Context")
678
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
679
+ @user.assign_role(role, context)
680
+ @user.roles_for?(nil).should be_false
681
+ @user.roles_for?(Context).should be_false
682
+ end
683
+
684
+ it "should return true if any roles are assigned to the subject within the provided context" do
685
+ nil_admin = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
686
+ class_admin = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
687
+ class_mod = Role.create(:name => 'Moderator', :slug => 'moderator', :level => 80, :context_type => 'Context')
688
+ @user.assign_role(nil_admin, Context)
689
+ @user.assign_role(class_admin, Context)
690
+ @user.assign_role(class_mod, Context)
691
+ @user.roles_for?(Context).should be_true
692
+ end
693
+
694
+ context "when forcing context" do
695
+ it "should only evaluate roles that match the context exactly" do
696
+ admin_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
697
+ @user.assign_role(admin_role, nil)
698
+ @user.roles_for?(nil).should be_true
699
+ @user.roles_for?(Context).should be_true
700
+ @user.roles_for?(Context, true).should be_false
701
+ end
702
+ end
703
+ end
704
+ end
705
+
706
+ describe "PermissionMethods" do
707
+ before(:each) do
708
+ User.acts_as_authorization_subject
709
+ Role.acts_as_authorization_role
710
+ Permission.acts_as_authorization_permission
711
+ end
712
+
713
+ it "should provide the model with has_many associations for permission_subjects and permissions" do
714
+ user = User.create(:name => "Test User")
715
+ User.reflections.keys.should include(:permission_users)
716
+ User.reflections.keys.should include(:permissions)
717
+ user.should respond_to(:permission_users)
718
+ user.should respond_to(:permissions)
719
+ end
720
+
721
+ it "should use the reflection classes to create the has_many associations" do
722
+ Soldier.acts_as_authorization_subject :permission_class => :skill, :role_class => :rank
723
+ Skill.acts_as_authorization_permission :subject_class => :soldier, :role_class => :rank
724
+ soldier = Soldier.create(:name => "Test User")
725
+ Soldier.reflections.keys.should include(:skill_soldiers)
726
+ Soldier.reflections.keys.should include(:skills)
727
+ soldier.should respond_to(:skill_soldiers)
728
+ soldier.should respond_to(:skills)
729
+ end
730
+
731
+ describe "assign_permission" do
732
+ before(:each) do
733
+ @user = User.create(:name => "Test User")
734
+ end
735
+
736
+ it "should require a permission object or slug" do
737
+ expect { @user.assign_permission }.to raise_exception
738
+ end
739
+
740
+ it "should accept an optional context" do
741
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
742
+ expect { @user.assign_permission(:edit, nil) }.to_not raise_exception
743
+ end
744
+
745
+ it "should use nil context when none is provided" do
746
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
747
+ permission_user = @user.assign_permission(:edit)
748
+ permission_user.id.should_not be_nil
749
+ permission_user.context_type.should be_nil
750
+ end
751
+
752
+ it "should use the context when one is provided" do
753
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
754
+ context = Context.create(:name => "Test Context")
755
+
756
+ class_permission_user = @user.assign_permission(permission, Context)
757
+ class_permission_user.id.should_not be_nil
758
+ class_permission_user.context_type.should == 'Context'
759
+ class_permission_user.context_id.should be_nil
760
+
761
+ inst_permission_user = @user.assign_permission(permission, context)
762
+ inst_permission_user.id.should_not be_nil
763
+ inst_permission_user.context_type.should == 'Context'
764
+ inst_permission_user.context_id.should == context.id
765
+ end
766
+
767
+ it "should use target_permission to lookup the closest contextual match when a permission slug is provided" do
768
+ context = Context.create(:name => "Test Context")
769
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
770
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
771
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
772
+
773
+ nil_permission_user = @user.assign_permission(:edit, nil)
774
+ nil_permission_user.id.should_not be_nil
775
+ nil_permission_user.context_type.should be_nil
776
+ nil_permission_user.context_id.should be_nil
777
+ nil_permission_user.permission.id.should == nil_permission.id
778
+
779
+ class_permission_user = @user.assign_permission(:edit, Context)
780
+ class_permission_user.id.should_not be_nil
781
+ class_permission_user.context_type.should == 'Context'
782
+ class_permission_user.context_id.should be_nil
783
+ class_permission_user.permission.id.should == class_permission.id
784
+
785
+ inst_permission_user = @user.assign_permission(:edit, context)
786
+ inst_permission_user.id.should_not be_nil
787
+ inst_permission_user.context_type.should == 'Context'
788
+ inst_permission_user.context_id.should == context.id
789
+ inst_permission_user.permission.id.should == inst_permission.id
790
+ end
791
+
792
+ it "should use the permission object when one is provided" do
793
+ context = Context.create(:name => "Test Context")
794
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
795
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
796
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
797
+
798
+ class_permission_user = @user.assign_permission(nil_permission, Context)
799
+ class_permission_user.id.should_not be_nil
800
+ class_permission_user.context_type.should == 'Context'
801
+ class_permission_user.context_id.should be_nil
802
+ class_permission_user.permission.id.should == nil_permission.id
803
+
804
+ inst_permission_user = @user.assign_permission(nil_permission, context)
805
+ inst_permission_user.id.should_not be_nil
806
+ inst_permission_user.context_type.should == 'Context'
807
+ inst_permission_user.context_id.should == context.id
808
+ inst_permission_user.permission.id.should == nil_permission.id
809
+ end
810
+
811
+ it "should fail and return false if the provided permission is nil" do
812
+ @user.assign_permission(nil).should be_false
813
+ @user.assign_permission(nil, Context).should be_false
814
+ end
815
+
816
+ it "should fail and return false if the provided permission cannot be used within the provided context" do
817
+ context = Context.create(:name => "Test Context")
818
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
819
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
820
+
821
+ @user.assign_permission(class_permission, nil).should be_false
822
+ @user.assign_permission(inst_permission, nil).should be_false
823
+ @user.assign_permission(inst_permission, Context).should be_false
824
+ end
825
+
826
+ it "should create the permission_subjects record to link the subject to the provided permission" do
827
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
828
+ @user.assign_permission(permission)
829
+ PermissionUser.where(:user_id => @user.id, :permission_id => permission.id).count.should == 1
830
+ end
831
+
832
+ it "should fail and return false if the provided permission is already assigned in the provided context" do
833
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
834
+ context = Context.create(:name => "Test Context")
835
+ @user.assign_permission(permission)
836
+ @user.assign_permission(permission).should be_false
837
+ @user.assign_permission(permission, Context)
838
+ @user.assign_permission(permission, Context).should be_false
839
+ @user.assign_permission(permission, context)
840
+ @user.assign_permission(permission, context).should be_false
841
+ end
842
+
843
+ context "when forcing context" do
844
+ it "should not go up the context chain to find the permission when a permission slug is provided" do
845
+ context = Context.create(:name => "Test Context")
846
+
847
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
848
+ nil_permission_user = @user.assign_permission(:edit, nil)
849
+ nil_permission_user.id.should_not be_nil
850
+ nil_permission_user.context_type.should be_nil
851
+ nil_permission_user.context_id.should be_nil
852
+ nil_permission_user.permission.id.should == nil_permission.id
853
+
854
+ @user.assign_permission(:edit, Context, true).should be_false
855
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
856
+ class_permission_user = @user.assign_permission(:edit, Context, true)
857
+ class_permission_user.id.should_not be_nil
858
+ class_permission_user.context_type.should == 'Context'
859
+ class_permission_user.context_id.should be_nil
860
+ class_permission_user.permission.id.should == class_permission.id
861
+
862
+ @user.assign_permission(:edit, context, true).should be_false
863
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
864
+ inst_permission_user = @user.assign_permission(:edit, context, true)
865
+ inst_permission_user.id.should_not be_nil
866
+ inst_permission_user.context_type.should == 'Context'
867
+ inst_permission_user.context_id.should == context.id
868
+ inst_permission_user.permission.id.should == inst_permission.id
869
+ end
870
+ end
871
+ end
872
+
873
+ describe "unassign_permission" do
874
+ before(:each) do
875
+ @user = User.create(:name => "Test User")
876
+ end
877
+
878
+ it "should require a permission object or slug" do
879
+ expect { @user.unassign_permission }.to raise_exception
880
+ end
881
+
882
+ it "should accept an optional context" do
883
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
884
+ expect { @user.unassign_permission(:edit, nil) }.to_not raise_exception
885
+ end
886
+
887
+ it "should use nil context when none is provided" do
888
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
889
+ @user.assign_permission(:edit, nil)
890
+ @user.assign_permission(:edit, Context)
891
+
892
+ unassigned = @user.unassign_permission(:edit)
893
+ unassigned.should be_an_instance_of(PermissionUser)
894
+ permissions = PermissionUser.where(:user_id => @user.id, :permission_id => permission.id)
895
+ permissions.length.should == 1
896
+ permissions[0].context_type.should == 'Context'
897
+ end
898
+
899
+ it "should use target_permission to lookup the closest contextual match when a permission slug is provided" do
900
+ context = Context.create(:name => "Test Context")
901
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
902
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
903
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
904
+ @user.assign_permission(nil_permission, nil)
905
+ @user.assign_permission(class_permission, Context)
906
+ @user.assign_permission(nil_permission, Context)
907
+ @user.assign_permission(inst_permission, context)
908
+ @user.assign_permission(class_permission, context)
909
+
910
+ @user.unassign_permission(:edit, context).permission_id.should == inst_permission.id
911
+ @user.unassign_permission(:edit, context).should be_false
912
+ @user.unassign_permission(:edit, Context).permission_id.should == class_permission.id
913
+ @user.unassign_permission(:edit, Context).should be_false
914
+ end
915
+
916
+ it "should use the permission object when one is provided" do
917
+ context = Context.create(:name => "Test Context")
918
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
919
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
920
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
921
+ @user.assign_permission(nil_permission, nil)
922
+ @user.assign_permission(class_permission, Context)
923
+ @user.assign_permission(nil_permission, Context)
924
+ @user.assign_permission(inst_permission, context)
925
+ @user.assign_permission(class_permission, context)
926
+
927
+ @user.unassign_permission(class_permission, context).permission_id.should == class_permission.id
928
+ @user.unassign_permission(inst_permission, context).permission_id.should == inst_permission.id
929
+ @user.unassign_permission(nil_permission, Context).permission_id.should == nil_permission.id
930
+ @user.unassign_permission(class_permission, Context).permission_id.should == class_permission.id
931
+ end
932
+
933
+ it "should fail and return false if the provided permission is nil" do
934
+ @user.unassign_permission(nil).should be_false
935
+ @user.unassign_permission(nil, Context).should be_false
936
+ end
937
+
938
+ it "should remove the permission_subjects record that links the subject to the provided permission" do
939
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
940
+ @user.assign_permission(permission)
941
+ PermissionUser.where(:user_id => @user.id, :permission_id => permission.id).count.should == 1
942
+ @user.unassign_permission(permission)
943
+ PermissionUser.where(:user_id => @user.id, :permission_id => permission.id).count.should == 0
944
+ end
945
+
946
+ it "should fail and return false if the provided permission is not assigned in the provided context" do
947
+ context = Context.create(:name => "Test Context")
948
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
949
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
950
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
951
+ @user.assign_permission(nil_permission, Context)
952
+ @user.assign_permission(class_permission, context)
953
+
954
+ @user.unassign_permission(inst_permission, context).should be_false
955
+ @user.unassign_permission(nil_permission, nil).should be_false
956
+ @user.unassign_permission(class_permission, Context).should be_false
957
+ end
958
+
959
+ context "when forcing context" do
960
+ it "should not go up the context chain to find the permission when a permission slug is provided" do
961
+ context = Context.create(:name => "Test Context")
962
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
963
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
964
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
965
+ @user.assign_permission(nil_permission, nil)
966
+ @user.assign_permission(class_permission, Context)
967
+ @user.assign_permission(nil_permission, Context)
968
+ @user.assign_permission(inst_permission, context)
969
+ @user.assign_permission(class_permission, context)
970
+
971
+ @user.unassign_permission(:edit, context, true).permission_id.should == inst_permission.id
972
+ inst_permission.destroy
973
+ @user.unassign_permission(:edit, context, true).should be_false
974
+ @user.unassign_permission(:edit, Context, true).permission_id.should == class_permission.id
975
+ class_permission.destroy
976
+ @user.unassign_permission(:edit, Context, true).should be_false
977
+ end
978
+ end
979
+ end
980
+
981
+ describe "has_permission?" do
982
+ before(:each) do
983
+ @user = User.create(:name => "Test User")
984
+ end
985
+
986
+ it "should require a permission object or slug" do
987
+ expect { @user.has_permission? }.to raise_exception
988
+ end
989
+
990
+ it "should accept an optional context" do
991
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
992
+ expect { @user.has_permission?(:edit, nil) }.to_not raise_exception
993
+ end
994
+
995
+ it "should use nil context when none is provided" do
996
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
997
+ @user.assign_permission(:edit, Context)
998
+ @user.has_permission?(:edit).should be_false
999
+ @user.assign_permission(:edit, nil)
1000
+ @user.has_permission?(:edit).should be_true
1001
+ end
1002
+
1003
+ it "should use target_permission to lookup the closest contextual match when a permission slug is provided" do
1004
+ context = Context.create(:name => "Test Context")
1005
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
1006
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
1007
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
1008
+ @user.assign_permission(nil_permission, Context)
1009
+ @user.assign_permission(class_permission, context)
1010
+
1011
+ @user.has_permission?(:edit, Context).should be_false
1012
+ @user.has_permission?(:edit, context).should be_false
1013
+
1014
+ @user.assign_permission(class_permission, Context)
1015
+ @user.assign_permission(inst_permission, context)
1016
+
1017
+ @user.has_permission?(:edit, Context).should be_true
1018
+ @user.has_permission?(:edit, context).should be_true
1019
+ end
1020
+
1021
+ it "should use the permission object when one is provided" do
1022
+ context = Context.create(:name => "Test Context")
1023
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
1024
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
1025
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
1026
+ @user.assign_permission(nil_permission, Context)
1027
+ @user.assign_permission(class_permission, context)
1028
+
1029
+ @user.has_permission?(nil_permission, Context).should be_true
1030
+ @user.has_permission?(class_permission, context).should be_true
1031
+ @user.has_permission?(class_permission, Context).should be_false
1032
+ @user.has_permission?(inst_permission, context).should be_false
1033
+
1034
+ @user.assign_permission(class_permission, Context)
1035
+ @user.assign_permission(inst_permission, context)
1036
+
1037
+ @user.has_permission?(class_permission, Context).should be_true
1038
+ @user.has_permission?(inst_permission, context).should be_true
1039
+ end
1040
+
1041
+ it "should return false if the provided permission is nil" do
1042
+ @user.has_permission?(nil).should be_false
1043
+ @user.has_permission?(nil, Context).should be_false
1044
+ end
1045
+
1046
+ it "should look up the context chain for the assigned permission" do
1047
+ context = Context.create(:name => "Test Context")
1048
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
1049
+ @user.assign_permission(permission, nil)
1050
+ @user.has_permission?(:edit, Context).should be_true
1051
+ @user.has_permission?(:edit, context).should be_true
1052
+ @user.unassign_permission(permission, nil)
1053
+ @user.assign_permission(permission, Context)
1054
+ @user.has_permission?(:edit, context).should be_true
1055
+ end
1056
+
1057
+ it "should return false if the provided permission is not assigned to the subject within the context chain" do
1058
+ context = Context.create(:name => "Test Context")
1059
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
1060
+ @user.has_permission?(permission, context).should be_false
1061
+ @user.has_permission?(:edit, Context).should be_false
1062
+ @user.has_permission?(permission, nil).should be_false
1063
+
1064
+ @user.assign_permission(:edit, context)
1065
+ @user.has_permission?(:edit, context).should_not be_false
1066
+ @user.has_permission?(permission, Context).should be_false
1067
+ @user.has_permission?(:edit, nil).should be_false
1068
+
1069
+ @user.assign_permission(:edit, Context)
1070
+ @user.has_permission?(:edit, context).should_not be_false
1071
+ @user.has_permission?(permission, Context).should_not be_false
1072
+ @user.has_permission?(permission, nil).should be_false
1073
+ end
1074
+
1075
+ context "when forcing context" do
1076
+ it "should not go up the context chain to find the permission when a permission slug is provided" do
1077
+ context = Context.create(:name => "Test Context")
1078
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
1079
+ @user.assign_permission(nil_permission, Context)
1080
+ @user.has_permission?(:edit, Context, false).should be_true
1081
+ @user.has_permission?(:edit, Context, true).should be_false
1082
+
1083
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
1084
+ @user.assign_permission(class_permission, context)
1085
+ @user.has_permission?(:edit, context, false).should be_true
1086
+ @user.has_permission?(:edit, context, true).should be_false
1087
+ end
1088
+ end
1089
+ end
1090
+
1091
+ describe "permissions_for" do
1092
+ before(:each) do
1093
+ @user = User.create(:name => "Test User")
1094
+ end
1095
+
1096
+ it "should accept an optional context" do
1097
+ expect { @user.permissions_for(nil) }.to_not raise_exception
1098
+ end
1099
+
1100
+ it "should use nil context when none is provided" do
1101
+ edit_permission = Permission.create(:name => 'Edit', :slug => 'edit')
1102
+ @user.assign_permission(edit_permission, Context)
1103
+ @user.permissions_for.length.should == 0
1104
+ @user.assign_permission(edit_permission, nil)
1105
+ @user.permissions_for.length.should == 1
1106
+ end
1107
+
1108
+ it "should return an empty association array if no permissions are assigned to the subject within the provided context" do
1109
+ context = Context.create(:name => "Test Context")
1110
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
1111
+ @user.assign_permission(permission, context)
1112
+ @user.permissions_for(nil).length.should == 0
1113
+ @user.permissions_for(Context).length.should == 0
1114
+ end
1115
+
1116
+ it "should return all permissions assigned to the subject within the provided context" do
1117
+ nil_edit = Permission.create(:name => 'Edit', :slug => 'edit')
1118
+ class_edit = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
1119
+ class_view = Permission.create(:name => 'View', :slug => 'view', :context_type => 'Context')
1120
+ @user.assign_permission(nil_edit, Context)
1121
+ @user.assign_permission(class_edit, Context)
1122
+ @user.assign_permission(class_view, Context)
1123
+ @user.permissions_for(Context).length.should == 3
1124
+ end
1125
+
1126
+ context "when forcing context" do
1127
+ it "should only return permissions that match the context exactly" do
1128
+ edit_permission = Permission.create(:name => 'Edit', :slug => 'edit')
1129
+ view_permission = Permission.create(:name => 'View', :slug => 'view')
1130
+ @user.assign_permission(edit_permission, nil)
1131
+ @user.assign_permission(view_permission, nil)
1132
+ @user.permissions_for(nil).length.should == 2
1133
+ @user.permissions_for(Context).length.should == 2
1134
+ @user.permissions_for(Context, true).length.should == 0
1135
+ end
1136
+ end
1137
+ end
1138
+
1139
+ describe "permissions_for?" do
1140
+ before(:each) do
1141
+ @user = User.create(:name => "Test User")
1142
+ end
1143
+
1144
+ it "should accept an optional context" do
1145
+ expect { @user.permissions_for?(nil) }.to_not raise_exception
1146
+ end
1147
+
1148
+ it "should use nil context when none is provided" do
1149
+ edit_permission = Permission.create(:name => 'Edit', :slug => 'edit')
1150
+ @user.assign_permission(edit_permission, Context)
1151
+ @user.permissions_for?.should be_false
1152
+ @user.assign_permission(edit_permission, nil)
1153
+ @user.permissions_for?.should be_true
1154
+ end
1155
+
1156
+ it "should return false if no permissions are assigned to the subject within the provided context" do
1157
+ context = Context.create(:name => "Test Context")
1158
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
1159
+ @user.assign_permission(permission, context)
1160
+ @user.permissions_for?(nil).should be_false
1161
+ @user.permissions_for?(Context).should be_false
1162
+ end
1163
+
1164
+ it "should return true if any permissions are assigned to the subject within the provided context" do
1165
+ nil_edit = Permission.create(:name => 'Edit', :slug => 'edit')
1166
+ class_edit = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
1167
+ class_view = Permission.create(:name => 'View', :slug => 'view', :context_type => 'Context')
1168
+ @user.assign_permission(nil_edit, Context)
1169
+ @user.assign_permission(class_edit, Context)
1170
+ @user.assign_permission(class_view, Context)
1171
+ @user.permissions_for?(Context).should be_true
1172
+ end
1173
+
1174
+ context "when forcing context" do
1175
+ it "should only evaluate permissions that match the context exactly" do
1176
+ edit_permission = Permission.create(:name => 'Edit', :slug => 'edit')
1177
+ @user.assign_permission(edit_permission, nil)
1178
+ @user.permissions_for?(nil).should be_true
1179
+ @user.permissions_for?(Context).should be_true
1180
+ @user.permissions_for?(Context, true).should be_false
1181
+ end
1182
+ end
1183
+ end
1184
+
1185
+ end
1186
+ end