cancannible 0.0.1

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.
@@ -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