zuul 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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