cancannible 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,67 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cancannible do
4
+ let(:grantee_class) { Member }
5
+ let(:grantee) { grantee_class.create! }
6
+
7
+ describe "#abilities" do
8
+ subject { grantee.abilities }
9
+
10
+ context "when get_cached_abilities provided" do
11
+ before do
12
+ Cancannible.get_cached_abilities = proc{|grantee| "get_cached_abilities for #{grantee.id}" }
13
+ end
14
+ it "should returned the cached object" do
15
+ should eql("get_cached_abilities for #{grantee.id}")
16
+ end
17
+ context "unless reload requested" do
18
+ subject { grantee.abilities(true) }
19
+ it { should be_an(Ability) }
20
+ end
21
+ end
22
+
23
+ context "when store_cached_abilities provided" do
24
+ before do
25
+ @stored = nil
26
+ Cancannible.store_cached_abilities = proc{ |grantee,ability| @stored = { grantee_id: grantee.id, ability: ability } }
27
+ end
28
+ it "should store the cached object" do
29
+ expect { subject }.to change { @stored }.from(nil)
30
+ expect(@stored[:grantee_id]).to eql(grantee.id)
31
+ expect(@stored[:ability]).to be_an(Ability)
32
+ end
33
+ end
34
+
35
+ context "when get and store cached_abilities provided" do
36
+ before do
37
+ @stored = nil
38
+ @store = 0
39
+ Cancannible.get_cached_abilities = proc{|grantee| @stored }
40
+ Cancannible.store_cached_abilities = proc{ |grantee,ability| @store += 1 ; @stored = { grantee_id: grantee.id, ability: ability } }
41
+ end
42
+ it "should store the cached object on the first call" do
43
+ expect { subject }.to change { @stored }.from(nil)
44
+ expect(@store).to eql(1)
45
+ expect(@stored[:grantee_id]).to eql(grantee.id)
46
+ expect(@stored[:ability]).to be_an(Ability)
47
+ end
48
+ it "should return the cached object on the second call" do
49
+ expect { subject }.to change { @stored }.from(nil)
50
+ expect(@store).to eql(1)
51
+ expect { grantee.abilities }.to_not change { @store }
52
+ expect(grantee.abilities[:grantee_id]).to eql(grantee.id)
53
+ expect(grantee.abilities[:ability]).to be_an(Ability)
54
+ end
55
+ it "should re-cache object on the second call if refresh requested" do
56
+ expect { subject }.to change { @stored }.from(nil)
57
+ expect(@store).to eql(1)
58
+ expect { grantee.abilities(true) }.to change { @store }.from(1).to(2)
59
+ expect(grantee.abilities[:grantee_id]).to eql(grantee.id)
60
+ expect(grantee.abilities[:ability]).to be_an(Ability)
61
+ end
62
+ end
63
+
64
+
65
+ end
66
+
67
+ end
@@ -0,0 +1,17 @@
1
+ require 'spec_helper'
2
+
3
+ describe Cancannible do
4
+ let(:grantee_class) { Member }
5
+ let(:grantee) { grantee_class.create! }
6
+
7
+ describe "#get_cached_abilities" do
8
+ let(:flag) { nil }
9
+ before do
10
+ Cancannible.get_cached_abilities = proc{|user| puts "get_cached_abilities" }
11
+ end
12
+ subject { grantee.abilities }
13
+ it "should call" do
14
+ subject
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,223 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe Cancannible do
5
+ let(:grantee_class) { User }
6
+ let(:ability) { :blow }
7
+ let(:username) { 'username' }
8
+
9
+ subject(:grantee) { grantee_class.create!(username: username) }
10
+
11
+ describe "#can?" do
12
+
13
+ context "with custom attribute association restriction" do
14
+ let(:resource_class) { Widget }
15
+ before do
16
+ Cancannible.setup do |config|
17
+ config.refine_access category_id: :category_ids
18
+ end
19
+ allow(grantee).to receive(:category_ids).and_return([1,3])
20
+ grantee.can(ability,resource_class)
21
+ end
22
+ let!(:resource) { resource_class.create(category_id: category_id) }
23
+ subject { grantee.can?(ability,resource) }
24
+ context "with resource within scope" do
25
+ let(:category_id) { 3 }
26
+ it { should be_truthy }
27
+ end
28
+ context "with resource in nil scope" do
29
+ let(:category_id) { nil }
30
+ it { should be_falsey }
31
+ end
32
+ context "with resource not in scope" do
33
+ let(:category_id) { 2 }
34
+ it { should be_falsey }
35
+ end
36
+ end
37
+
38
+ context "with custom attribute association restriction and allow_nil" do
39
+ let(:resource_class) { Widget }
40
+ before do
41
+ Cancannible.setup do |config|
42
+ config.refine_access category_id: :category_ids, allow_nil: true
43
+ end
44
+ allow(grantee).to receive(:category_ids).and_return([1,3])
45
+ grantee.can(ability,resource_class)
46
+ end
47
+ let!(:resource) { resource_class.create(category_id: category_id) }
48
+ subject { grantee.can?(ability,resource) }
49
+ context "with resource within scope" do
50
+ let(:category_id) { 3 }
51
+ it { should be_truthy }
52
+ end
53
+ context "with resource in nil scope" do
54
+ let(:category_id) { nil }
55
+ it { should be_truthy }
56
+ end
57
+ context "with resource not in scope" do
58
+ let(:category_id) { 2 }
59
+ it { should be_falsey }
60
+ end
61
+ end
62
+
63
+ context "with custom attribute association restriction scoped by ability" do
64
+ let(:resource_class) { Widget }
65
+ let(:other_ability) { :suck }
66
+ before do
67
+ Cancannible.setup do |config|
68
+ config.refine_access category_id: :category_ids, scope: ability
69
+ end
70
+ allow(grantee).to receive(:category_ids).and_return([1,3])
71
+ grantee.can(ability,resource_class)
72
+ grantee.can(other_ability,resource_class)
73
+ end
74
+ let!(:resource) { resource_class.create(category_id: category_id) }
75
+ context "when scoped ability" do
76
+ subject { grantee.can?(ability,resource) }
77
+ context "with resource within scope" do
78
+ let(:category_id) { 3 }
79
+ it { should be_truthy }
80
+ end
81
+ context "with resource not in scope" do
82
+ let(:category_id) { 2 }
83
+ it { should be_falsey }
84
+ end
85
+ end
86
+ context "when other ability" do
87
+ subject { grantee.can?(other_ability,resource) }
88
+ context "with resource within scoped ability" do
89
+ let(:category_id) { 3 }
90
+ it { should be_truthy }
91
+ end
92
+ context "with resource not in scoped ability" do
93
+ let(:category_id) { 2 }
94
+ it { should be_truthy }
95
+ end
96
+ end
97
+ end
98
+
99
+ context "with custom attribute association restriction scoped by ability exception" do
100
+ let(:resource_class) { Widget }
101
+ let(:other_ability) { :suck }
102
+ before do
103
+ Cancannible.setup do |config|
104
+ config.refine_access category_id: :category_ids, except: other_ability
105
+ end
106
+ allow(grantee).to receive(:category_ids).and_return([1,3])
107
+ grantee.can(ability,resource_class)
108
+ grantee.can(other_ability,resource_class)
109
+ end
110
+ let!(:resource) { resource_class.create(category_id: category_id) }
111
+ context "when scoped ability" do
112
+ subject { grantee.can?(ability,resource) }
113
+ context "with resource within scope" do
114
+ let(:category_id) { 3 }
115
+ it { should be_truthy }
116
+ end
117
+ context "with resource not in scope" do
118
+ let(:category_id) { 2 }
119
+ it { should be_falsey }
120
+ end
121
+ end
122
+ context "when other ability" do
123
+ subject { grantee.can?(other_ability,resource) }
124
+ context "with resource within scoped ability" do
125
+ let(:category_id) { 3 }
126
+ it { should be_truthy }
127
+ end
128
+ context "with resource not in scoped ability" do
129
+ let(:category_id) { 2 }
130
+ it { should be_truthy }
131
+ end
132
+ end
133
+ end
134
+
135
+ context "with custom attribute association restriction scoped by ability array" do
136
+ let(:resource_class) { Widget }
137
+ let(:other_ability) { :suck }
138
+ before do
139
+ Cancannible.setup do |config|
140
+ config.refine_access category_id: :category_ids, scope: [ability,:another_ability]
141
+ end
142
+ allow(grantee).to receive(:category_ids).and_return([1,3])
143
+ grantee.can(ability,resource_class)
144
+ grantee.can(other_ability,resource_class)
145
+ end
146
+ let!(:resource) { resource_class.create(category_id: category_id) }
147
+ context "when scoped ability" do
148
+ subject { grantee.can?(ability,resource) }
149
+ context "with resource within scope" do
150
+ let(:category_id) { 3 }
151
+ it { should be_truthy }
152
+ end
153
+ context "with resource not in scope" do
154
+ let(:category_id) { 2 }
155
+ it { should be_falsey }
156
+ end
157
+ end
158
+ context "when other ability" do
159
+ subject { grantee.can?(other_ability,resource) }
160
+ context "with resource within scoped ability" do
161
+ let(:category_id) { 3 }
162
+ it { should be_truthy }
163
+ end
164
+ context "with resource not in scoped ability" do
165
+ let(:category_id) { 2 }
166
+ it { should be_truthy }
167
+ end
168
+ end
169
+ end
170
+ context "with if-conditional custom attribute association restriction" do
171
+ let(:resource_class) { Widget }
172
+ before do
173
+ Cancannible.setup do |config|
174
+ config.refine_access category_id: :category_ids, if: proc{ |grantee,model_resource| grantee.username == 'restrict by categories' }
175
+ end
176
+ allow(grantee).to receive(:category_ids).and_return([1,3])
177
+ grantee.can(ability,resource_class)
178
+ end
179
+ let!(:resource) { resource_class.create(category_id: category_id) }
180
+ subject { grantee.can?(ability,resource) }
181
+ context "with resource not in scope but restriction not applicable" do
182
+ let(:category_id) { 2 }
183
+ it { should be_truthy }
184
+ end
185
+ context "with resource not in scope and restriction applicable" do
186
+ let(:username) { 'restrict by categories' }
187
+ let(:category_id) { 2 }
188
+ it { should be_falsey }
189
+ end
190
+ end
191
+
192
+ context "with combined attribute association and fixed value restriction" do
193
+ let(:resource_class) { Widget }
194
+ before do
195
+ Cancannible.setup do |config|
196
+ config.refine_access category_id: :category_ids, name: 'Test'
197
+ end
198
+ allow(grantee).to receive(:category_ids).and_return([1,3])
199
+ grantee.can(ability,resource_class)
200
+ end
201
+ let!(:resource) { resource_class.create(category_id: category_id, name: name) }
202
+ subject { grantee.can?(ability,resource) }
203
+ context "with resource within scope" do
204
+ let(:name) { 'Test' }
205
+ let(:category_id) { 3 }
206
+ it { should be_truthy }
207
+ end
208
+ context "with resource not in scope (excluded by attribute association)" do
209
+ let(:name) { 'Test' }
210
+ let(:category_id) { 2 }
211
+ it { should be_falsey }
212
+ end
213
+ context "with resource not in scope (excluded by fixed value)" do
214
+ let(:name) { 'Not Test' }
215
+ let(:category_id) { 3 }
216
+ it { should be_falsey }
217
+ end
218
+ end
219
+
220
+
221
+ end
222
+
223
+ end
@@ -0,0 +1,145 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe Cancannible do
5
+ let(:grantee_class) { User }
6
+
7
+ context "with mulitple sources of permissions inheritance" do
8
+
9
+ describe "##inheritable_permissions" do
10
+ subject { grantee_class.inheritable_permissions }
11
+ it { should eql([:roles, :group]) }
12
+ end
13
+
14
+ let!(:role_a) { Role.create! }
15
+ let!(:role_b) { Role.create! }
16
+ let!(:group_a) { Group.create! }
17
+ let!(:group_b) { Group.create! }
18
+ subject(:grantee) {
19
+ u = grantee_class.new(group: group_a)
20
+ u.roles << role_a
21
+ u.save!
22
+ u
23
+ }
24
+
25
+ context "with a symbolic resource" do
26
+ let!(:resource) { :something }
27
+
28
+ describe "#can?" do
29
+ subject { grantee.can?(:read, resource) }
30
+ context "when no permission" do
31
+ it { should be_falsey }
32
+ end
33
+ context "when permission assigned to grantee themselves" do
34
+ before { grantee.can(:read, resource) }
35
+ it { should be_truthy }
36
+ end
37
+ context "when permission inherited thru belongs_to association" do
38
+ before { group_a.can(:read, resource) }
39
+ it { should be_truthy }
40
+ end
41
+ context "when permission inherited thru habtm association" do
42
+ before { role_a.can(:read, resource) }
43
+ it { should be_truthy }
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+
50
+ context "with a resource class" do
51
+ let!(:resource) { Widget }
52
+
53
+ describe "#can?" do
54
+ subject { grantee.can?(:read, resource) }
55
+ context "when permission is not set" do
56
+ it { should be_falsey }
57
+ end
58
+ context "when permission assigned to grantee themselves" do
59
+ before { grantee.can(:read, resource) }
60
+ it { should be_truthy }
61
+ end
62
+ context "when permission inherited thru belongs_to association" do
63
+ before { group_a.can(:read, resource) }
64
+ it { should be_truthy }
65
+ end
66
+ context "when permission inherited thru habtm association" do
67
+ before { role_a.can(:read, resource) }
68
+ it { should be_truthy }
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ context "with a resource instance" do
75
+ let!(:resource) { Widget.create! }
76
+ let!(:other_resource) { Widget.create! }
77
+
78
+ describe "#can?" do
79
+ subject { grantee.can?(:read, resource) }
80
+ context "when permission is not set" do
81
+ it { should be_falsey }
82
+ end
83
+ context "when permission assigned to grantee themselves" do
84
+ before { grantee.can(:read, resource) }
85
+ it { should be_truthy }
86
+ context "but for other instances" do
87
+ subject { grantee.can?(:read, other_resource) }
88
+ it { should be_falsey }
89
+ end
90
+ end
91
+ context "when permission inherited thru belongs_to association" do
92
+ before { group_a.can(:read, resource) }
93
+ it { should be_truthy }
94
+ context "but for other instances" do
95
+ subject { grantee.can?(:read, other_resource) }
96
+ it { should be_falsey }
97
+ end
98
+ end
99
+ context "when permission inherited thru habtm association" do
100
+ before { role_a.can(:read, resource) }
101
+ it { should be_truthy }
102
+ context "but for other instances" do
103
+ subject { grantee.can?(:read, other_resource) }
104
+ it { should be_falsey }
105
+ end
106
+ end
107
+ end
108
+
109
+ describe "#cannot?" do
110
+ subject { grantee.cannot?(:read, resource) }
111
+ context "when permission is not asserted for the grantee themselves" do
112
+ it { should be_truthy }
113
+ end
114
+ context "when permission is not asserted but can is for the grantee themselves" do
115
+ before { grantee.can(:read, resource) }
116
+ it { should be_falsey }
117
+ end
118
+ context "when permission is not asserted but can is thru belongs_to association" do
119
+ before { group_a.can(:read, resource) }
120
+ it { should be_falsey }
121
+ end
122
+ context "when permission is not asserted but can is thru habtm association" do
123
+ before { role_a.can(:read, resource) }
124
+ it { should be_falsey }
125
+ end
126
+ context "when permission is asserted for the grantee themselves" do
127
+ before { grantee.cannot(:read, resource) }
128
+ it { should be_truthy }
129
+ end
130
+ context "when permission is asserted thru belongs_to association" do
131
+ before { group_a.cannot(:read, resource) }
132
+ it { should be_truthy }
133
+ end
134
+ context "when permission is asserted thru habtm association" do
135
+ before { role_a.cannot(:read, resource) }
136
+ it { should be_truthy }
137
+ end
138
+ end
139
+
140
+
141
+ end
142
+
143
+ end
144
+
145
+ end