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,174 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Zuul::ActiveRecord::Permission" do
4
+
5
+ describe "accessible attributes" do
6
+ before(:each) do
7
+ Permission.acts_as_authorization_permission
8
+ end
9
+
10
+ it "should allow mass assignment of :name" do
11
+ permission = Permission.new(:name => 'Edit')
12
+ permission.name.should == 'Edit'
13
+ end
14
+
15
+ it "should allow mass assignment of :slug" do
16
+ permission = Permission.new(:slug => 'edit')
17
+ permission.slug.should == 'edit'
18
+ end
19
+
20
+ it "should allow mass assignment of :context" do
21
+ context = Context.create(:name => "Test Context")
22
+ permission = Permission.new(:context => context)
23
+ permission.context_type.should == 'Context'
24
+ permission.context_id.should == context.id
25
+ end
26
+
27
+ it "should allow mass assignment of :context_type" do
28
+ permission = Permission.new(:context_type => 'Context')
29
+ permission.context_type.should == 'Context'
30
+ end
31
+
32
+ it "should allow mass assignment of :context_id" do
33
+ permission = Permission.new(:context_id => 1)
34
+ permission.context_id.should == 1
35
+ end
36
+ end
37
+
38
+ context "validations for core permission fields" do
39
+ before(:each) do
40
+ Permission.acts_as_authorization_permission
41
+ end
42
+
43
+ it "should validate presence of slug" do
44
+ permission = Permission.new(:name => 'Edit')
45
+ permission.valid?.should be_false
46
+ permission.errors.keys.should include(:slug)
47
+ end
48
+
49
+ it "should validate format of slug" do
50
+ permission = Permission.new(:name => 'Edit', :slug => 'edit')
51
+ permission.valid?.should be_true
52
+ permission.slug = 'adm in'
53
+ permission.valid?.should be_false
54
+ permission.errors.keys.should include(:slug)
55
+ permission.slug = 'ad*&^;'
56
+ permission.valid?.should be_false
57
+ permission.errors.keys.should include(:slug)
58
+ permission.slug = '{:edit}'
59
+ permission.valid?.should be_false
60
+ permission.errors.keys.should include(:slug)
61
+ end
62
+
63
+ it "should validate uniqueness of slug scoped to context_type, context_id" do
64
+ Permission.create(:name => 'Edit', :slug => 'edit')
65
+ permission = Permission.new(:name => 'Edit', :slug => 'edit')
66
+ permission.valid?.should be_false
67
+ permission.errors.keys.should include(:slug)
68
+
69
+ Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context').valid?.should be_true
70
+ permission = Permission.new(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
71
+ permission.valid?.should be_false
72
+ permission.errors.keys.should include(:slug)
73
+
74
+ Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => 1).valid?.should be_true
75
+ permission = Permission.new(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => 1)
76
+ permission.valid?.should be_false
77
+ permission.errors.keys.should include(:slug)
78
+ end
79
+ end
80
+
81
+ it "should provide the model with has_many associations for permission_subjects and subjects" do
82
+ Permission.acts_as_authorization_permission
83
+ Permission.reflections.keys.should include(:permission_users)
84
+ Permission.reflections.keys.should include(:users)
85
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
86
+ permission.should respond_to(:permission_users)
87
+ permission.should respond_to(:users)
88
+ end
89
+
90
+ it "should use the reflection classes to create the has_many associations" do
91
+ Skill.acts_as_authorization_permission :subject_class => :soldier, :role_class => :rank
92
+ Skill.reflections.keys.should include(:skill_soldiers)
93
+ Skill.reflections.keys.should include(:soldiers)
94
+ skill = Skill.create(:name => 'Marksman', :slug => 'marksman')
95
+ skill.should respond_to(:skill_soldiers)
96
+ skill.should respond_to(:soldiers)
97
+ end
98
+
99
+ it "should provide the model with has_many associations for permission_roles and roles" do
100
+ Permission.acts_as_authorization_permission
101
+ Permission.reflections.keys.should include(:permission_roles)
102
+ Permission.reflections.keys.should include(:roles)
103
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
104
+ permission.should respond_to(:permission_roles)
105
+ permission.should respond_to(:roles)
106
+ end
107
+
108
+ it "should use the reflection classes to create the has_many associations" do
109
+ Skill.acts_as_authorization_permission :subject_class => :soldier, :role_class => :rank
110
+ Skill.reflections.keys.should include(:rank_skills)
111
+ Skill.reflections.keys.should include(:ranks)
112
+ skill = Skill.create(:name => 'Marksman', :slug => 'marksman')
113
+ skill.should respond_to(:rank_skills)
114
+ skill.should respond_to(:ranks)
115
+ end
116
+
117
+ describe "#context" do
118
+ before(:each) do
119
+ Permission.acts_as_authorization_permission
120
+ end
121
+
122
+ it "should return a Zuul::Context object" do
123
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
124
+ permission.context.should be_a(Zuul::Context)
125
+ end
126
+
127
+ it "should return a Zuul::Context object that represents the context of the permission" do
128
+ context = Context.create(:name => "Test Context")
129
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
130
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
131
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
132
+ nil_permission.context.to_context.should be_nil
133
+ class_permission.context.to_context.should == Context
134
+ inst_permission.context.to_context.should be_a(Context)
135
+ inst_permission.context.to_context.id.should == context.id
136
+ end
137
+ end
138
+
139
+ describe "#context=" do
140
+ before(:each) do
141
+ Permission.acts_as_authorization_permission
142
+ @permission = Permission.create(:name => 'Edit', :slug => 'edit')
143
+ end
144
+
145
+ it "should allow passing a nil context" do
146
+ expect { @permission.context = nil }.to_not raise_exception
147
+ end
148
+
149
+ it "should allow passing a class context" do
150
+ expect { @permission.context = Context }.to_not raise_exception
151
+ end
152
+
153
+ it "should allow passing an instance context" do
154
+ context = Context.create(:name => "Test Context")
155
+ expect { @permission.context = context }.to_not raise_exception
156
+ end
157
+
158
+ it "should allow passing an existing Zuul::Context" do
159
+ expect { @permission.context = Zuul::Context.new }.to_not raise_exception
160
+ end
161
+
162
+ it "should accept a context and set the context_type and context_id based on the passed context" do
163
+ context = Context.create(:name => "Test Context")
164
+ @permission.context_type.should be_nil
165
+ @permission.context_id.should be_nil
166
+ @permission.context = Context
167
+ @permission.context_type.should == "Context"
168
+ @permission.context_id.should be_nil
169
+ @permission.context = context
170
+ @permission.context_type.should == "Context"
171
+ @permission.context_id.should == context.id
172
+ end
173
+ end
174
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Zuul::ActiveRecord::PermissionSubject" do
4
+ before(:each) do
5
+ Permission.acts_as_authorization_permission
6
+ end
7
+
8
+ describe "accessible attributes" do
9
+ it "should allow mass assignment of permission class foreign key" do
10
+ pu = PermissionUser.new(:permission_id => 1)
11
+ pu.permission_id.should == 1
12
+ end
13
+
14
+ it "should allow mass assignment of subject class foreign key" do
15
+ pu = PermissionUser.new(:user_id => 1)
16
+ pu.user_id.should == 1
17
+ end
18
+
19
+ it "should allow mass assignment of :context" do
20
+ context = Context.create(:name => "Test Context")
21
+ pu = PermissionUser.new(:context => context)
22
+ pu.context_type.should == 'Context'
23
+ pu.context_id.should == context.id
24
+ end
25
+
26
+ it "should allow mass assignment of :context_type" do
27
+ pu = PermissionUser.new(:context_type => 'Context')
28
+ pu.context_type.should == 'Context'
29
+ end
30
+
31
+ it "should allow mass assignment of :context_id" do
32
+ pu = PermissionUser.new(:context_id => 1)
33
+ pu.context_id.should == 1
34
+ end
35
+ end
36
+
37
+ context "validations for core permission fields" do
38
+ it "should validate presence of permission class foreign key" do
39
+ pu = PermissionUser.new()
40
+ pu.valid?.should be_false
41
+ pu.errors.keys.should include(:permission_id)
42
+ end
43
+
44
+ it "should validate presence of subject class foreign key" do
45
+ pu = PermissionUser.new()
46
+ pu.valid?.should be_false
47
+ pu.errors.keys.should include(:user_id)
48
+ end
49
+
50
+ it "should validate uniqueness of permission class foreign key scoped to context_type, context_id and the subject class foreign key" do
51
+ PermissionUser.create(:permission_id => 1, :user_id => 1)
52
+ pu = PermissionUser.create(:permission_id => 1, :user_id => 1)
53
+ pu.valid?.should be_false
54
+ pu.errors.keys.should include(:permission_id)
55
+
56
+ PermissionUser.create(:permission_id => 1, :user_id => 1, :context_type => 'Context').valid?.should be_true
57
+ pu = PermissionUser.create(:permission_id => 1, :user_id => 1, :context_type => 'Context')
58
+ pu.valid?.should be_false
59
+ pu.errors.keys.should include(:permission_id)
60
+
61
+ PermissionUser.create(:permission_id => 1, :user_id => 1, :context_type => 'Context', :context_id => 1).valid?.should be_true
62
+ pu = PermissionUser.create(:permission_id => 1, :user_id => 1, :context_type => 'Context', :context_id => 1)
63
+ pu.valid?.should be_false
64
+ pu.errors.keys.should include(:permission_id)
65
+ end
66
+
67
+ it "should validate numericality of permission class foreign key with integers only" do
68
+ pu = PermissionUser.new(:permission_id => 'a', :user_id => 1)
69
+ pu.valid?.should be_false
70
+ pu.errors.keys.should include(:permission_id)
71
+ pu.permission_id = 1.3
72
+ pu.valid?.should be_false
73
+ pu.errors.keys.should include(:permission_id)
74
+ end
75
+ end
76
+
77
+ it "should provide the model with belongs_to associations for permissions and subjects" do
78
+ PermissionUser.reflections.keys.should include(:permission)
79
+ PermissionUser.reflections.keys.should include(:user)
80
+ pu = PermissionUser.create(:permission_id => 1, :use_id => 1)
81
+ pu.should respond_to(:permission)
82
+ pu.should respond_to(:user)
83
+ end
84
+ end
@@ -0,0 +1,694 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Zuul::ActiveRecord::Role" do
4
+
5
+ describe "accessible attributes" do
6
+ before(:each) do
7
+ Role.acts_as_authorization_role
8
+ end
9
+
10
+ it "should allow mass assignment of :name" do
11
+ role = Role.new(:name => 'Admin')
12
+ role.name.should == 'Admin'
13
+ end
14
+
15
+ it "should allow mass assignment of :slug" do
16
+ role = Role.new(:slug => 'admin')
17
+ role.slug.should == 'admin'
18
+ end
19
+
20
+ it "should allow mass assignment of :level" do
21
+ role = Role.new(:level => 100)
22
+ role.level.should == 100
23
+ end
24
+
25
+ it "should allow mass assignment of :context" do
26
+ context = Context.create(:name => "Test Context")
27
+ role = Role.new(:context => context)
28
+ role.context_type.should == 'Context'
29
+ role.context_id.should == context.id
30
+ end
31
+
32
+ it "should allow mass assignment of :context_type" do
33
+ role = Role.new(:context_type => 'Context')
34
+ role.context_type.should == 'Context'
35
+ end
36
+
37
+ it "should allow mass assignment of :context_id" do
38
+ role = Role.new(:context_id => 1)
39
+ role.context_id.should == 1
40
+ end
41
+ end
42
+
43
+ context "validations for core role fields" do
44
+ before(:each) do
45
+ Role.acts_as_authorization_role
46
+ end
47
+
48
+ it "should validate presence of level" do
49
+ role = Role.new(:name => 'Admin', :slug => 'admin')
50
+ role.valid?.should be_false
51
+ role.errors.keys.should include(:level)
52
+ end
53
+
54
+ it "should validate presence of slug" do
55
+ role = Role.new(:name => 'Admin', :level => 100)
56
+ role.valid?.should be_false
57
+ role.errors.keys.should include(:slug)
58
+ end
59
+
60
+ it "should validate format of slug" do
61
+ role = Role.new(:name => 'Admin', :slug => 'admin', :level => 100)
62
+ role.valid?.should be_true
63
+ role.slug = 'adm in'
64
+ role.valid?.should be_false
65
+ role.errors.keys.should include(:slug)
66
+ role.slug = 'ad*&^;'
67
+ role.valid?.should be_false
68
+ role.errors.keys.should include(:slug)
69
+ role.slug = '{:admin}'
70
+ role.valid?.should be_false
71
+ role.errors.keys.should include(:slug)
72
+ end
73
+
74
+ it "should validate uniqueness of slug scoped to context_type, context_id" do
75
+ Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
76
+ role = Role.new(:name => 'Admin', :slug => 'admin', :level => 100)
77
+ role.valid?.should be_false
78
+ role.errors.keys.should include(:slug)
79
+
80
+ Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context').valid?.should be_true
81
+ role = Role.new(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
82
+ role.valid?.should be_false
83
+ role.errors.keys.should include(:slug)
84
+
85
+ Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => 1).valid?.should be_true
86
+ role = Role.new(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => 1)
87
+ role.valid?.should be_false
88
+ role.errors.keys.should include(:slug)
89
+ end
90
+
91
+ it "should validate uniqueness of level scoped to context_type, context_id" do
92
+ Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
93
+ role = Role.new(:name => 'Admin', :slug => 'admin', :level => 100)
94
+ role.valid?.should be_false
95
+ role.errors.keys.should include(:level)
96
+
97
+ Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context').valid?.should be_true
98
+ role = Role.new(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
99
+ role.valid?.should be_false
100
+ role.errors.keys.should include(:level)
101
+
102
+ Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => 1).valid?.should be_true
103
+ role = Role.new(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => 1)
104
+ role.valid?.should be_false
105
+ role.errors.keys.should include(:level)
106
+ end
107
+
108
+ it "should validate numericality of level with integers only" do
109
+ role = Role.new(:name => 'Admin', :slug => 'admin', :level => 'a')
110
+ role.valid?.should be_false
111
+ role.errors.keys.should include(:level)
112
+ role.level = 1.3
113
+ role.valid?.should be_false
114
+ role.errors.keys.should include(:level)
115
+ end
116
+ end
117
+
118
+ it "should provide the model with has_many associations for role_subjects and subjects" do
119
+ Role.acts_as_authorization_role
120
+ Role.reflections.keys.should include(:role_users)
121
+ Role.reflections.keys.should include(:users)
122
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
123
+ role.should respond_to(:role_users)
124
+ role.should respond_to(:users)
125
+ end
126
+
127
+ it "should use the reflection classes to create the has_many associations" do
128
+ Rank.acts_as_authorization_role :subject_class => :soldier, :with_permissions => false
129
+ Rank.reflections.keys.should include(:rank_soldiers)
130
+ Rank.reflections.keys.should include(:soldiers)
131
+ rank = Rank.create(:name => 'General', :slug => 'general', :level => 100)
132
+ rank.should respond_to(:rank_soldiers)
133
+ rank.should respond_to(:soldiers)
134
+ end
135
+
136
+ describe "#context" do
137
+ before(:each) do
138
+ Role.acts_as_authorization_role
139
+ end
140
+
141
+ it "should return a Zuul::Context object" do
142
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
143
+ role.context.should be_a(Zuul::Context)
144
+ end
145
+
146
+ it "should return a Zuul::Context object that represents the context of the role" do
147
+ context = Context.create(:name => "Test Context")
148
+ nil_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
149
+ class_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context')
150
+ inst_role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100, :context_type => 'Context', :context_id => context.id)
151
+ nil_role.context.to_context.should be_nil
152
+ class_role.context.to_context.should == Context
153
+ inst_role.context.to_context.should be_a(Context)
154
+ inst_role.context.to_context.id.should == context.id
155
+ end
156
+ end
157
+
158
+ describe "#context=" do
159
+ before(:each) do
160
+ Role.acts_as_authorization_role
161
+ @role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
162
+ end
163
+
164
+ it "should allow passing a nil context" do
165
+ expect { @role.context = nil }.to_not raise_exception
166
+ end
167
+
168
+ it "should allow passing a class context" do
169
+ expect { @role.context = Context }.to_not raise_exception
170
+ end
171
+
172
+ it "should allow passing an instance context" do
173
+ context = Context.create(:name => "Test Context")
174
+ expect { @role.context = context }.to_not raise_exception
175
+ end
176
+
177
+ it "should allow passing an existing Zuul::Context" do
178
+ expect { @role.context = Zuul::Context.new }.to_not raise_exception
179
+ end
180
+
181
+ it "should accept a context and set the context_type and context_id based on the passed context" do
182
+ context = Context.create(:name => "Test Context")
183
+ @role.context_type.should be_nil
184
+ @role.context_id.should be_nil
185
+ @role.context = Context
186
+ @role.context_type.should == "Context"
187
+ @role.context_id.should be_nil
188
+ @role.context = context
189
+ @role.context_type.should == "Context"
190
+ @role.context_id.should == context.id
191
+ end
192
+ end
193
+
194
+ context "with permissions disabled" do
195
+ before(:each) do
196
+ Role.acts_as_authorization_role :with_permissions => false
197
+ end
198
+
199
+ it "should not provide the model with has_many associations for permission_roles and permissions" do
200
+ Role.reflections.keys.should_not include(:permission_roles)
201
+ Role.reflections.keys.should_not include(:permissions)
202
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
203
+ role.should_not respond_to(:permission_roles)
204
+ role.should_not respond_to(:permissions)
205
+ end
206
+
207
+ it "should not provide the model with permissions methods" do
208
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
209
+ role.should_not respond_to(:assign_permission)
210
+ role.should_not respond_to(:unassign_permission)
211
+ role.should_not respond_to(:has_permission?)
212
+ role.should_not respond_to(:permissions_for)
213
+ role.should_not respond_to(:permissions_for?)
214
+ end
215
+ end
216
+
217
+ context "with permissions enabled" do
218
+ before(:each) do
219
+ Role.acts_as_authorization_role
220
+ Permission.acts_as_authorization_permission
221
+ end
222
+
223
+ it "should provide the model with has_many associations for permission_roles and permissions" do
224
+ Role.reflections.keys.should include(:permission_roles)
225
+ Role.reflections.keys.should include(:permissions)
226
+ role = Role.create(:name => 'Admin', :slug => 'admin', :level => 100)
227
+ role.should respond_to(:permission_roles)
228
+ role.should respond_to(:permissions)
229
+ end
230
+
231
+ it "should use the reflection classes to create the has_many associations" do
232
+ Rank.acts_as_authorization_role :subject_class => :soldier, :permission_class => :skill
233
+ Rank.reflections.keys.should include(:rank_skills)
234
+ Rank.reflections.keys.should include(:skills)
235
+ rank = Rank.create(:name => 'General', :slug => 'general', :level => 100)
236
+ rank.should respond_to(:rank_skills)
237
+ rank.should respond_to(:skills)
238
+ end
239
+
240
+ describe "assign_permission" do
241
+ before(:each) do
242
+ @role = Role.create(:name => "Admin", :slug => "admin", :level => 100)
243
+ end
244
+
245
+ it "should require a permission object or slug" do
246
+ expect { @role.assign_permission }.to raise_exception
247
+ end
248
+
249
+ it "should accept an optional context" do
250
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
251
+ expect { @role.assign_permission(:edit, nil) }.to_not raise_exception
252
+ end
253
+
254
+ it "should use nil context when none is provided" do
255
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
256
+ permission_role = @role.assign_permission(:edit)
257
+ permission_role.id.should_not be_nil
258
+ permission_role.context_type.should be_nil
259
+ end
260
+
261
+ it "should use the context when one is provided" do
262
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
263
+ context = Context.create(:name => "Test Context")
264
+
265
+ class_permission_role = @role.assign_permission(permission, Context)
266
+ class_permission_role.id.should_not be_nil
267
+ class_permission_role.context_type.should == 'Context'
268
+ class_permission_role.context_id.should be_nil
269
+
270
+ inst_permission_role = @role.assign_permission(permission, context)
271
+ inst_permission_role.id.should_not be_nil
272
+ inst_permission_role.context_type.should == 'Context'
273
+ inst_permission_role.context_id.should == context.id
274
+ end
275
+
276
+ it "should use target_permission to lookup the closest contextual match when a permission slug is provided" do
277
+ context = Context.create(:name => "Test Context")
278
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
279
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
280
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
281
+
282
+ nil_permission_role = @role.assign_permission(:edit, nil)
283
+ nil_permission_role.id.should_not be_nil
284
+ nil_permission_role.context_type.should be_nil
285
+ nil_permission_role.context_id.should be_nil
286
+ nil_permission_role.permission.should == nil_permission
287
+
288
+ class_permission_role = @role.assign_permission(:edit, Context)
289
+ class_permission_role.id.should_not be_nil
290
+ class_permission_role.context_type.should == 'Context'
291
+ class_permission_role.context_id.should be_nil
292
+ class_permission_role.permission.should == class_permission
293
+
294
+ inst_permission_role = @role.assign_permission(:edit, context)
295
+ inst_permission_role.id.should_not be_nil
296
+ inst_permission_role.context_type.should == 'Context'
297
+ inst_permission_role.context_id.should == context.id
298
+ inst_permission_role.permission.should == inst_permission
299
+ end
300
+
301
+ it "should use the permission object when one is provided" do
302
+ context = Context.create(:name => "Test Context")
303
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
304
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
305
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
306
+
307
+ class_permission_role = @role.assign_permission(nil_permission, Context)
308
+ class_permission_role.id.should_not be_nil
309
+ class_permission_role.context_type.should == 'Context'
310
+ class_permission_role.context_id.should be_nil
311
+ class_permission_role.permission.id.should == nil_permission.id
312
+
313
+ inst_permission_role = @role.assign_permission(nil_permission, context)
314
+ inst_permission_role.id.should_not be_nil
315
+ inst_permission_role.context_type.should == 'Context'
316
+ inst_permission_role.context_id.should == context.id
317
+ inst_permission_role.permission.id.should == nil_permission.id
318
+ end
319
+
320
+ it "should fail and return false if the provided permission is nil" do
321
+ @role.assign_permission(nil).should be_false
322
+ @role.assign_permission(nil, Context).should be_false
323
+ end
324
+
325
+ it "should fail and return false if the provided permission cannot be used within the provided context" do
326
+ context = Context.create(:name => "Test Context")
327
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
328
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
329
+
330
+ @role.assign_permission(class_permission, nil).should be_false
331
+ @role.assign_permission(inst_permission, nil).should be_false
332
+ @role.assign_permission(inst_permission, Context).should be_false
333
+ end
334
+
335
+ it "should create the permission_subjects record to link the subject to the provided permission" do
336
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
337
+ @role.assign_permission(permission)
338
+ PermissionRole.where(:role_id => @role.id, :permission_id => permission.id).count.should == 1
339
+ end
340
+
341
+ it "should fail and return false if the provided permission is already assigned in the provided context" do
342
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
343
+ context = Context.create(:name => "Test Context")
344
+ @role.assign_permission(permission)
345
+ @role.assign_permission(permission).should be_false
346
+ @role.assign_permission(permission, Context)
347
+ @role.assign_permission(permission, Context).should be_false
348
+ @role.assign_permission(permission, context)
349
+ @role.assign_permission(permission, context).should be_false
350
+ end
351
+
352
+ context "when forcing context" do
353
+ it "should not go up the context chain to find the permission when a permission slug is provided" do
354
+ context = Context.create(:name => "Test Context")
355
+
356
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
357
+ nil_permission_user = @role.assign_permission(:edit, nil)
358
+ nil_permission_user.id.should_not be_nil
359
+ nil_permission_user.context_type.should be_nil
360
+ nil_permission_user.context_id.should be_nil
361
+ nil_permission_user.permission.id.should == nil_permission.id
362
+
363
+ @role.assign_permission(:edit, Context, true).should be_false
364
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
365
+ class_permission_user = @role.assign_permission(:edit, Context, true)
366
+ class_permission_user.id.should_not be_nil
367
+ class_permission_user.context_type.should == 'Context'
368
+ class_permission_user.context_id.should be_nil
369
+ class_permission_user.permission.id.should == class_permission.id
370
+
371
+ @role.assign_permission(:edit, context, true).should be_false
372
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
373
+ inst_permission_user = @role.assign_permission(:edit, context, true)
374
+ inst_permission_user.id.should_not be_nil
375
+ inst_permission_user.context_type.should == 'Context'
376
+ inst_permission_user.context_id.should == context.id
377
+ inst_permission_user.permission.id.should == inst_permission.id
378
+ end
379
+ end
380
+ end
381
+
382
+ describe "unassign_permission" do
383
+ before(:each) do
384
+ @role = Role.create(:name => "Admin", :slug => "admin", :level => 100)
385
+ end
386
+
387
+ it "should require a permission object or slug" do
388
+ expect { @role.unassign_permission }.to raise_exception
389
+ end
390
+
391
+ it "should accept an optional context" do
392
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
393
+ expect { @role.unassign_permission(:edit, nil) }.to_not raise_exception
394
+ end
395
+
396
+ it "should use nil context when none is provided" do
397
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
398
+ @role.assign_permission(:edit, nil)
399
+ @role.assign_permission(:edit, Context)
400
+
401
+ unassigned = @role.unassign_permission(:edit)
402
+ unassigned.should be_an_instance_of(PermissionRole)
403
+ permissions = PermissionRole.where(:role_id => @role.id, :permission_id => permission.id)
404
+ permissions.length.should == 1
405
+ permissions[0].context_type.should == 'Context'
406
+ end
407
+
408
+ it "should use target_permission to lookup the closest contextual match when a permission slug is provided" do
409
+ context = Context.create(:name => "Test Context")
410
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
411
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
412
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
413
+ @role.assign_permission(nil_permission, nil)
414
+ @role.assign_permission(class_permission, Context)
415
+ @role.assign_permission(nil_permission, Context)
416
+ @role.assign_permission(inst_permission, context)
417
+ @role.assign_permission(class_permission, context)
418
+
419
+ @role.unassign_permission(:edit, context).permission_id.should == inst_permission.id
420
+ @role.unassign_permission(:edit, context).should be_false
421
+ @role.unassign_permission(:edit, Context).permission_id.should == class_permission.id
422
+ @role.unassign_permission(:edit, Context).should be_false
423
+ end
424
+
425
+ it "should use the permission object when one is provided" do
426
+ context = Context.create(:name => "Test Context")
427
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
428
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
429
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
430
+ @role.assign_permission(nil_permission, nil)
431
+ @role.assign_permission(class_permission, Context)
432
+ @role.assign_permission(nil_permission, Context)
433
+ @role.assign_permission(inst_permission, context)
434
+ @role.assign_permission(class_permission, context)
435
+
436
+ @role.unassign_permission(class_permission, context).permission_id.should == class_permission.id
437
+ @role.unassign_permission(inst_permission, context).permission_id.should == inst_permission.id
438
+ @role.unassign_permission(nil_permission, Context).permission_id.should == nil_permission.id
439
+ @role.unassign_permission(class_permission, Context).permission_id.should == class_permission.id
440
+ end
441
+
442
+ it "should fail and return false if the provided permission is nil" do
443
+ @role.unassign_permission(nil).should be_false
444
+ @role.unassign_permission(nil, Context).should be_false
445
+ end
446
+
447
+ it "should remove the permission_subjects record that links the subject to the provided permission" do
448
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
449
+ @role.assign_permission(permission)
450
+ PermissionRole.where(:role_id => @role.id, :permission_id => permission.id).count.should == 1
451
+ @role.unassign_permission(permission)
452
+ PermissionRole.where(:role_id => @role.id, :permission_id => permission.id).count.should == 0
453
+ end
454
+
455
+ it "should fail and return false if the provided permission is not assigned in the provided context" do
456
+ context = Context.create(:name => "Test Context")
457
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
458
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
459
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
460
+ @role.assign_permission(nil_permission, Context)
461
+ @role.assign_permission(class_permission, context)
462
+
463
+ @role.unassign_permission(inst_permission, context).should be_false
464
+ @role.unassign_permission(nil_permission, nil).should be_false
465
+ @role.unassign_permission(class_permission, Context).should be_false
466
+ end
467
+
468
+ context "when forcing context" do
469
+ it "should not go up the context chain to find the permission when a permission slug is provided" do
470
+ context = Context.create(:name => "Test Context")
471
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
472
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
473
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
474
+ @role.assign_permission(nil_permission, nil)
475
+ @role.assign_permission(class_permission, Context)
476
+ @role.assign_permission(nil_permission, Context)
477
+ @role.assign_permission(inst_permission, context)
478
+ @role.assign_permission(class_permission, context)
479
+
480
+ @role.unassign_permission(:edit, context, true).permission_id.should == inst_permission.id
481
+ inst_permission.destroy
482
+ @role.unassign_permission(:edit, context, true).should be_false
483
+ @role.unassign_permission(:edit, Context, true).permission_id.should == class_permission.id
484
+ class_permission.destroy
485
+ @role.unassign_permission(:edit, Context, true).should be_false
486
+ end
487
+ end
488
+ end
489
+
490
+ describe "has_permission?" do
491
+ before(:each) do
492
+ @role = Role.create(:name => "Admin", :slug => "admin", :level => 100)
493
+ end
494
+
495
+ it "should require a permission object or slug" do
496
+ expect { @role.has_permission? }.to raise_exception
497
+ end
498
+
499
+ it "should accept an optional context" do
500
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
501
+ expect { @role.has_permission?(:edit, nil) }.to_not raise_exception
502
+ end
503
+
504
+ it "should use nil context when none is provided" do
505
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
506
+ @role.assign_permission(:edit, Context)
507
+ @role.has_permission?(:edit).should be_false
508
+ @role.assign_permission(:edit, nil)
509
+ @role.has_permission?(:edit).should be_true
510
+ end
511
+
512
+ it "should use target_permission to lookup the closest contextual match when a permission slug is provided" do
513
+ context = Context.create(:name => "Test Context")
514
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
515
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
516
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
517
+ @role.assign_permission(nil_permission, Context)
518
+ @role.assign_permission(class_permission, context)
519
+
520
+ @role.has_permission?(:edit, Context).should be_false
521
+ @role.has_permission?(:edit, context).should be_false
522
+
523
+ @role.assign_permission(class_permission, Context)
524
+ @role.assign_permission(inst_permission, context)
525
+
526
+ @role.has_permission?(:edit, Context).should be_true
527
+ @role.has_permission?(:edit, context).should be_true
528
+ end
529
+
530
+ it "should use the permission object when one is provided" do
531
+ context = Context.create(:name => "Test Context")
532
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
533
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
534
+ inst_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context', :context_id => context.id)
535
+ @role.assign_permission(nil_permission, Context)
536
+ @role.assign_permission(class_permission, context)
537
+
538
+ @role.has_permission?(nil_permission, Context).should be_true
539
+ @role.has_permission?(class_permission, context).should be_true
540
+ @role.has_permission?(class_permission, Context).should be_false
541
+ @role.has_permission?(inst_permission, context).should be_false
542
+
543
+ @role.assign_permission(class_permission, Context)
544
+ @role.assign_permission(inst_permission, context)
545
+
546
+ @role.has_permission?(class_permission, Context).should be_true
547
+ @role.has_permission?(inst_permission, context).should be_true
548
+ end
549
+
550
+ it "should return false if the provided permission is nil" do
551
+ @role.has_permission?(nil).should be_false
552
+ @role.has_permission?(nil, Context).should be_false
553
+ end
554
+
555
+ it "should look up the context chain for the assigned permission" do
556
+ context = Context.create(:name => "Test Context")
557
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
558
+ @role.assign_permission(permission, nil)
559
+ @role.has_permission?(:edit, Context).should be_true
560
+ @role.has_permission?(:edit, context).should be_true
561
+ @role.unassign_permission(permission, nil)
562
+ @role.assign_permission(permission, Context)
563
+ @role.has_permission?(:edit, context).should be_true
564
+ end
565
+
566
+ it "should return false if the provided permission is not assigned to the subject within the context chain" do
567
+ context = Context.create(:name => "Test Context")
568
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
569
+ @role.has_permission?(permission, context).should be_false
570
+ @role.has_permission?(:edit, Context).should be_false
571
+ @role.has_permission?(permission, nil).should be_false
572
+
573
+ @role.assign_permission(:edit, context)
574
+ @role.has_permission?(:edit, context).should_not be_false
575
+ @role.has_permission?(permission, Context).should be_false
576
+ @role.has_permission?(:edit, nil).should be_false
577
+
578
+ @role.assign_permission(:edit, Context)
579
+ @role.has_permission?(:edit, context).should_not be_false
580
+ @role.has_permission?(permission, Context).should_not be_false
581
+ @role.has_permission?(permission, nil).should be_false
582
+ end
583
+
584
+ context "when forcing context" do
585
+ it "should not go up the context chain to find the permission when a permission slug is provided" do
586
+ context = Context.create(:name => "Test Context")
587
+ nil_permission = Permission.create(:name => 'Edit', :slug => 'edit')
588
+ @role.assign_permission(nil_permission, Context)
589
+ @role.has_permission?(:edit, Context, false).should be_true
590
+ @role.has_permission?(:edit, Context, true).should be_false
591
+
592
+ class_permission = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
593
+ @role.assign_permission(class_permission, context)
594
+ @role.has_permission?(:edit, context, false).should be_true
595
+ @role.has_permission?(:edit, context, true).should be_false
596
+ end
597
+ end
598
+ end
599
+
600
+ describe "permissions_for" do
601
+ before(:each) do
602
+ @role = Role.create(:name => "Admin", :slug => "admin", :level => 100)
603
+ end
604
+
605
+ it "should accept an optional context" do
606
+ expect { @role.permissions_for(nil) }.to_not raise_exception
607
+ end
608
+
609
+ it "should use nil context when none is provided" do
610
+ edit_permission = Permission.create(:name => 'Edit', :slug => 'edit')
611
+ @role.assign_permission(edit_permission, Context)
612
+ @role.permissions_for.length.should == 0
613
+ @role.assign_permission(edit_permission, nil)
614
+ @role.permissions_for.length.should == 1
615
+ end
616
+
617
+ it "should return an empty association array if no permissions are assigned to the subject within the provided context" do
618
+ context = Context.create(:name => "Test Context")
619
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
620
+ @role.assign_permission(permission, context)
621
+ @role.permissions_for(nil).length.should == 0
622
+ @role.permissions_for(Context).length.should == 0
623
+ end
624
+
625
+ it "should return all permissions assigned to the subject within the provided context" do
626
+ nil_edit = Permission.create(:name => 'Edit', :slug => 'edit')
627
+ class_edit = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
628
+ class_view = Permission.create(:name => 'View', :slug => 'view', :context_type => 'Context')
629
+ @role.assign_permission(nil_edit, Context)
630
+ @role.assign_permission(class_edit, Context)
631
+ @role.assign_permission(class_view, Context)
632
+ @role.permissions_for(Context).length.should == 3
633
+ end
634
+
635
+ context "when forcing context" do
636
+ it "should only return permissions that match the context exactly" do
637
+ edit_permission = Permission.create(:name => 'Edit', :slug => 'edit')
638
+ view_permission = Permission.create(:name => 'View', :slug => 'view')
639
+ @role.assign_permission(edit_permission, nil)
640
+ @role.assign_permission(view_permission, nil)
641
+ @role.permissions_for(nil).length.should == 2
642
+ @role.permissions_for(Context).length.should == 2
643
+ @role.permissions_for(Context, true).length.should == 0
644
+ end
645
+ end
646
+ end
647
+
648
+ describe "permissions_for?" do
649
+ before(:each) do
650
+ @role = Role.create(:name => "Admin", :slug => "admin", :level => 100)
651
+ end
652
+
653
+ it "should accept an optional context" do
654
+ expect { @role.permissions_for?(nil) }.to_not raise_exception
655
+ end
656
+
657
+ it "should use nil context when none is provided" do
658
+ edit_permission = Permission.create(:name => 'Edit', :slug => 'edit')
659
+ @role.assign_permission(edit_permission, Context)
660
+ @role.permissions_for?.should be_false
661
+ @role.assign_permission(edit_permission, nil)
662
+ @role.permissions_for?.should be_true
663
+ end
664
+
665
+ it "should return false if no permissions are assigned to the subject within the provided context" do
666
+ context = Context.create(:name => "Test Context")
667
+ permission = Permission.create(:name => 'Edit', :slug => 'edit')
668
+ @role.assign_permission(permission, context)
669
+ @role.permissions_for?(nil).should be_false
670
+ @role.permissions_for?(Context).should be_false
671
+ end
672
+
673
+ it "should return true if any permissions are assigned to the subject within the provided context" do
674
+ nil_edit = Permission.create(:name => 'Edit', :slug => 'edit')
675
+ class_edit = Permission.create(:name => 'Edit', :slug => 'edit', :context_type => 'Context')
676
+ class_view = Permission.create(:name => 'View', :slug => 'view', :context_type => 'Context')
677
+ @role.assign_permission(nil_edit, Context)
678
+ @role.assign_permission(class_edit, Context)
679
+ @role.assign_permission(class_view, Context)
680
+ @role.permissions_for?(Context).should be_true
681
+ end
682
+
683
+ context "when forcing context" do
684
+ it "should only evaluate permissions that match the context exactly" do
685
+ edit_permission = Permission.create(:name => 'Edit', :slug => 'edit')
686
+ @role.assign_permission(edit_permission, nil)
687
+ @role.permissions_for?(nil).should be_true
688
+ @role.permissions_for?(Context).should be_true
689
+ @role.permissions_for?(Context, true).should be_false
690
+ end
691
+ end
692
+ end
693
+ end
694
+ end