casbin-ruby 1.0.3 → 1.0.4
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.
- checksums.yaml +4 -4
- data/README.md +242 -0
- data/lib/casbin-ruby.rb +11 -0
- data/lib/casbin-ruby/config/config.rb +115 -0
- data/lib/casbin-ruby/core_enforcer.rb +356 -0
- data/lib/casbin-ruby/effect/allow_and_deny_effector.rb +23 -0
- data/lib/casbin-ruby/effect/allow_override_effector.rb +23 -0
- data/lib/casbin-ruby/effect/default_effector.rb +37 -0
- data/lib/casbin-ruby/effect/deny_override_effector.rb +23 -0
- data/lib/casbin-ruby/effect/effector.rb +18 -0
- data/lib/casbin-ruby/effect/priority_effector.rb +25 -0
- data/lib/casbin-ruby/enforcer.rb +189 -0
- data/lib/casbin-ruby/internal_enforcer.rb +73 -0
- data/lib/casbin-ruby/management_enforcer.rb +297 -0
- data/lib/casbin-ruby/model/assertion.rb +33 -0
- data/lib/casbin-ruby/model/function_map.rb +30 -0
- data/lib/casbin-ruby/model/model.rb +80 -0
- data/lib/casbin-ruby/model/policy.rb +161 -0
- data/lib/casbin-ruby/persist/adapter.rb +39 -0
- data/lib/casbin-ruby/persist/adapters/file_adapter.rb +53 -0
- data/lib/casbin-ruby/persist/batch_adapter.rb +16 -0
- data/lib/casbin-ruby/persist/filtered_adapter.rb +17 -0
- data/lib/casbin-ruby/rbac/default_role_manager/role.rb +54 -0
- data/lib/casbin-ruby/rbac/default_role_manager/role_manager.rb +146 -0
- data/lib/casbin-ruby/rbac/role_manager.rb +22 -0
- data/lib/casbin-ruby/synced_enforcer.rb +39 -0
- data/lib/casbin-ruby/util.rb +80 -0
- data/lib/casbin-ruby/util/builtin_operators.rb +105 -0
- data/lib/casbin-ruby/util/evaluator.rb +27 -0
- data/lib/casbin-ruby/util/thread_lock.rb +19 -0
- data/lib/casbin-ruby/version.rb +5 -0
- data/spec/casbin/config/config_spec.rb +66 -0
- data/spec/casbin/core_enforcer_spec.rb +473 -0
- data/spec/casbin/enforcer_spec.rb +302 -0
- data/spec/casbin/model/function_map_spec.rb +28 -0
- data/spec/casbin/rbac/default_role_manager/role_manager_spec.rb +131 -0
- data/spec/casbin/rbac/default_role_manager/role_spec.rb +84 -0
- data/spec/casbin/util/builtin_operators_spec.rb +205 -0
- data/spec/casbin/util_spec.rb +98 -0
- data/spec/support/model_helper.rb +9 -0
- metadata +51 -3
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'casbin-ruby/config/config'
|
4
|
+
|
5
|
+
describe Casbin::Config::Config do
|
6
|
+
let(:path) { File.expand_path('test.ini', __dir__) }
|
7
|
+
let(:config) { described_class.new_config(path) }
|
8
|
+
|
9
|
+
describe '#new_config_from_text' do
|
10
|
+
let(:config) { described_class.new_config_from_text(text) }
|
11
|
+
let(:text) do
|
12
|
+
text = nil
|
13
|
+
File.open(path, 'r:UTF-8') do |f|
|
14
|
+
text = f.readlines.join
|
15
|
+
end
|
16
|
+
|
17
|
+
text
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'reads config from text' do
|
21
|
+
expect(config.get('debug')).to eq 'true'
|
22
|
+
expect(config.get('redis::redis.key')).to eq 'push1,push2'
|
23
|
+
expect(config.get('math::math.i64')).to eq '64'
|
24
|
+
expect(config.get('other::name')).to eq 'ATC自动化测试^-^&($#……#'
|
25
|
+
expect(config.get('multi1::name')).to eq 'r.sub==p.sub && r.obj==p.obj'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '#get' do
|
30
|
+
it 'default::key' do
|
31
|
+
expect(config.get('debug')).to eq 'true'
|
32
|
+
expect(config.get('url')).to eq 'act.wiki'
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'redis::key' do
|
36
|
+
expect(config.get('redis::redis.key')).to eq 'push1,push2'
|
37
|
+
expect(config.get('mysql::mysql.dev.host')).to eq '127.0.0.1'
|
38
|
+
expect(config.get('mysql::mysql.master.host')).to eq '10.0.0.1'
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'math::key test' do
|
42
|
+
expect(config.get('math::math.i64')).to eq '64'
|
43
|
+
expect(config.get('math::math.f64')).to eq '64.1'
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'other::key test' do
|
47
|
+
expect(config.get('other::name')).to eq 'ATC自动化测试^-^&($#……#'
|
48
|
+
expect(config.get('other::key1')).to eq 'test key'
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'multi line' do
|
52
|
+
expect(config.get('multi1::name')).to eq 'r.sub==p.sub && r.obj==p.obj'
|
53
|
+
expect(config.get('multi2::name')).to eq 'r.sub==p.sub && r.obj==p.obj'
|
54
|
+
expect(config.get('multi3::name')).to eq 'r.sub==p.sub && r.obj==p.obj'
|
55
|
+
expect(config.get('multi4::name')).to eq ''
|
56
|
+
expect(config.get('multi5::name')).to eq 'r.sub==p.sub && r.obj==p.obj'
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#set' do
|
61
|
+
it 'set other::key1' do
|
62
|
+
config.set('other::key1', 'new test key')
|
63
|
+
expect(config.get('other::key1')).to eq 'new test key'
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,473 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'casbin-ruby/core_enforcer'
|
4
|
+
require 'support/model_helper'
|
5
|
+
|
6
|
+
describe Casbin::CoreEnforcer do
|
7
|
+
let(:model) { Casbin::Model::Model.new }
|
8
|
+
let(:adapter) { Casbin::Persist::Adapter.new }
|
9
|
+
let(:enforcer) { described_class.new model, adapter }
|
10
|
+
let(:watcher) { instance_double 'watcher' }
|
11
|
+
|
12
|
+
describe '#initalize' do
|
13
|
+
shared_examples 'creates new enforcer' do
|
14
|
+
it { expect(enforcer).not_to be_nil }
|
15
|
+
end
|
16
|
+
|
17
|
+
context 'when model is a string (path)' do
|
18
|
+
let(:model) { model_config 'basic' }
|
19
|
+
|
20
|
+
context 'when adapter is a string (path)' do
|
21
|
+
let(:adapter) { policy_file 'basic' }
|
22
|
+
|
23
|
+
it_behaves_like 'creates new enforcer'
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'when adapter is a special object' do
|
27
|
+
it_behaves_like 'creates new enforcer'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when model is a special object' do
|
32
|
+
context 'when adapter is a string (path)' do
|
33
|
+
let(:adapter) { policy_file 'basic' }
|
34
|
+
|
35
|
+
it 'raises exception' do
|
36
|
+
expect { enforcer }.to raise_error StandardError, 'Invalid parameters for enforcer.'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when adapter is a special object' do
|
41
|
+
let(:model) { model_config 'basic' }
|
42
|
+
|
43
|
+
it_behaves_like 'creates new enforcer'
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#enforce' do
|
49
|
+
subject { enforcer.enforce(*request) }
|
50
|
+
|
51
|
+
shared_examples 'correctly enforces rules' do |requests|
|
52
|
+
requests.each do |request_data, result|
|
53
|
+
context "with #{request_data.inspect}" do
|
54
|
+
let(:request) { request_data }
|
55
|
+
|
56
|
+
it { is_expected.to eq(result) }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'with basic' do
|
62
|
+
let(:model) { model_config 'basic' }
|
63
|
+
let(:adapter) { policy_file 'basic' }
|
64
|
+
|
65
|
+
requests = {
|
66
|
+
%w[alice data1 read] => true,
|
67
|
+
%w[bob data2 write] => true,
|
68
|
+
%w[alice data1 write] => false,
|
69
|
+
%w[bob data2 read] => false,
|
70
|
+
|
71
|
+
%w[admin2 data1 read] => false
|
72
|
+
}
|
73
|
+
|
74
|
+
it_behaves_like 'correctly enforces rules', requests
|
75
|
+
end
|
76
|
+
|
77
|
+
context 'with basic with root' do
|
78
|
+
let(:model) { model_config 'basic_with_root' }
|
79
|
+
let(:adapter) { policy_file 'basic' }
|
80
|
+
|
81
|
+
requests = {
|
82
|
+
%w[alice data1 read] => true,
|
83
|
+
%w[bob data2 write] => true,
|
84
|
+
%w[alice data1 write] => false,
|
85
|
+
%w[bob data2 read] => false,
|
86
|
+
|
87
|
+
%w[admin2 data1 read] => false,
|
88
|
+
|
89
|
+
%w[root data1 read] => true,
|
90
|
+
%w[root data1 write] => true,
|
91
|
+
%w[root data2 read] => true,
|
92
|
+
%w[root data2 write] => true
|
93
|
+
}
|
94
|
+
|
95
|
+
it_behaves_like 'correctly enforces rules', requests
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'with basic without users' do
|
99
|
+
let(:model) { model_config 'basic_without_users' }
|
100
|
+
let(:adapter) { policy_file 'basic_without_users' }
|
101
|
+
|
102
|
+
requests = {
|
103
|
+
%w[data1 read] => true,
|
104
|
+
%w[data1 write] => false,
|
105
|
+
%w[data2 read] => false,
|
106
|
+
%w[data2 write] => true,
|
107
|
+
%w[data3 read] => false,
|
108
|
+
%w[data3 write] => false
|
109
|
+
}
|
110
|
+
|
111
|
+
it_behaves_like 'correctly enforces rules', requests
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'with basic without resources' do
|
115
|
+
let(:model) { model_config 'basic_without_resources' }
|
116
|
+
let(:adapter) { policy_file 'basic_without_resources' }
|
117
|
+
|
118
|
+
requests = {
|
119
|
+
%w[alice read] => true,
|
120
|
+
%w[alice write] => false,
|
121
|
+
%w[bob read] => false,
|
122
|
+
%w[bob write] => true,
|
123
|
+
%w[charlie read] => false,
|
124
|
+
%w[charlie write] => false
|
125
|
+
}
|
126
|
+
|
127
|
+
it_behaves_like 'correctly enforces rules', requests
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'with RBAC' do
|
131
|
+
let(:model) { model_config 'rbac' }
|
132
|
+
let(:adapter) { policy_file 'rbac' }
|
133
|
+
|
134
|
+
requests = {
|
135
|
+
%w[alice data1 read] => true,
|
136
|
+
%w[alice data1 write] => false,
|
137
|
+
%w[alice data2 read] => true,
|
138
|
+
|
139
|
+
%w[bob data1 read] => false,
|
140
|
+
|
141
|
+
%w[data2_admin data2 read] => true,
|
142
|
+
%w[data2_admin data1 read] => false
|
143
|
+
}
|
144
|
+
|
145
|
+
it_behaves_like 'correctly enforces rules', requests
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'with RBAC with domains' do
|
149
|
+
let(:model) { model_config 'rbac_with_domains' }
|
150
|
+
let(:adapter) { policy_file 'rbac_with_domains' }
|
151
|
+
|
152
|
+
requests = {
|
153
|
+
%w[alice domain1 data1 read] => true,
|
154
|
+
%w[alice domain2 data1 read] => false,
|
155
|
+
%w[alice domain1 data2 read] => false,
|
156
|
+
%w[alice domain1 data1 delete] => false,
|
157
|
+
|
158
|
+
%w[bob domain1 data1 read] => false,
|
159
|
+
%w[bob domain2 data2 read] => true,
|
160
|
+
%w[bob domain1 data1 write] => false,
|
161
|
+
%w[bob domain2 data2 write] => true,
|
162
|
+
|
163
|
+
%w[admin domain1 data1 read] => true,
|
164
|
+
%w[admin domain2 data2 read] => true,
|
165
|
+
%w[admin domain1 data1 write] => true,
|
166
|
+
%w[admin domain2 data2 write] => true
|
167
|
+
}
|
168
|
+
|
169
|
+
it_behaves_like 'correctly enforces rules', requests
|
170
|
+
end
|
171
|
+
|
172
|
+
context 'with RBAC with resource roles' do
|
173
|
+
let(:model) { model_config 'rbac_with_resource_roles' }
|
174
|
+
let(:adapter) { policy_file 'rbac_with_resource_roles' }
|
175
|
+
|
176
|
+
requests = {
|
177
|
+
%w[alice data1 read] => true,
|
178
|
+
%w[alice data1 write] => true,
|
179
|
+
%w[alice data2 read] => false,
|
180
|
+
%w[alice data2 write] => true,
|
181
|
+
%w[alice data3 read] => false,
|
182
|
+
%w[alice data3 write] => false,
|
183
|
+
|
184
|
+
%w[bob data1 read] => false,
|
185
|
+
%w[bob data1 write] => false,
|
186
|
+
%w[bob data2 read] => false,
|
187
|
+
%w[bob data2 write] => true,
|
188
|
+
%w[bob data3 read] => false,
|
189
|
+
%w[bob data3 write] => false,
|
190
|
+
|
191
|
+
%w[data_group_admin data1 read] => false,
|
192
|
+
%w[data_group_admin data1 write] => true,
|
193
|
+
%w[data_group_admin data2 read] => false,
|
194
|
+
%w[data_group_admin data2 write] => true,
|
195
|
+
%w[data_group_admin data3 read] => false,
|
196
|
+
%w[data_group_admin data3 write] => false,
|
197
|
+
|
198
|
+
%w[diana data1 read] => false
|
199
|
+
}
|
200
|
+
|
201
|
+
it_behaves_like 'correctly enforces rules', requests
|
202
|
+
end
|
203
|
+
|
204
|
+
context 'with RBAC with pattern' do
|
205
|
+
let(:model) { model_config 'rbac_with_pattern' }
|
206
|
+
let(:adapter) { policy_file 'rbac_with_pattern' }
|
207
|
+
|
208
|
+
requests = {
|
209
|
+
%w[alice /book/1 GET] => true,
|
210
|
+
%w[alice /book/1 POST] => false,
|
211
|
+
%w[alice /other/1 GET] => false
|
212
|
+
}
|
213
|
+
|
214
|
+
before do
|
215
|
+
enforcer.add_named_matching_func('g2',
|
216
|
+
->(key1, key2) { Casbin::Util::BuiltinOperators.key_match2 key1, key2 })
|
217
|
+
end
|
218
|
+
|
219
|
+
it_behaves_like 'correctly enforces rules', requests
|
220
|
+
end
|
221
|
+
|
222
|
+
# This does not implemented in Python version. Examples was taken from here:
|
223
|
+
# https://casbin.org/en/editor (select "RBAC with all pattern" option)
|
224
|
+
#
|
225
|
+
# We should add the separate matching function for domain.
|
226
|
+
# https://github.com/casbin/casbin/blob/0c7aac93d766aeddea324d7a16fd8be1c700bca5/enforcer.go#L661
|
227
|
+
xcontext 'with RBAC with all pattern' do
|
228
|
+
let(:model) { model_config 'rbac_with_all_pattern' }
|
229
|
+
let(:adapter) { policy_file 'rbac_with_all_pattern' }
|
230
|
+
|
231
|
+
requests = {
|
232
|
+
%w[/book/1 domain1 data1 read] => true,
|
233
|
+
%w[/book/1 domain2 data2 write] => true,
|
234
|
+
|
235
|
+
%w[/domain1/book/1 domain1 data1 read] => true,
|
236
|
+
%w[/domain1/book/1 domain2 data2 write] => false
|
237
|
+
}
|
238
|
+
|
239
|
+
before do
|
240
|
+
matching_func = ->(key1, key2) { Util::BuiltinOperators.key_match2 key1, key2 }
|
241
|
+
enforcer.role_manager.add_matching_func matching_func
|
242
|
+
# enforcer.role_manager.add_domain_matching_func matching_func
|
243
|
+
end
|
244
|
+
|
245
|
+
it_behaves_like 'correctly enforces rules', requests
|
246
|
+
end
|
247
|
+
|
248
|
+
context 'with ABAC' do
|
249
|
+
let(:model) { model_config 'abac' }
|
250
|
+
|
251
|
+
requests = {
|
252
|
+
['alice', { 'Owner' => 'alice' }, 'read'] => true,
|
253
|
+
['alice', { 'Owner' => 'alice' }, 'write'] => true,
|
254
|
+
['alice', { 'Owner' => 'diana' }, 'read'] => false,
|
255
|
+
['alice', { 'Owner' => 'diana' }, 'write'] => false
|
256
|
+
}
|
257
|
+
|
258
|
+
it_behaves_like 'correctly enforces rules', requests
|
259
|
+
end
|
260
|
+
|
261
|
+
context 'with ABAC with eval' do
|
262
|
+
let(:model) { model_config 'abac_with_eval' }
|
263
|
+
let(:adapter) { policy_file 'abac_with_eval' }
|
264
|
+
|
265
|
+
requests = {
|
266
|
+
[{ 'Age' => 12, 'Position' => { 'Rank' => 1 } }, '/data1', 'read'] => false,
|
267
|
+
[{ 'Age' => 22, 'Position' => { 'Rank' => 1 } }, '/data1', 'read'] => true,
|
268
|
+
[{ 'Age' => 22, 'Position' => { 'Rank' => 1 } }, '/data1', 'write'] => false,
|
269
|
+
|
270
|
+
[{ 'Age' => 22, 'Position' => { 'Rank' => 1 } }, '/data2', 'read'] => false,
|
271
|
+
[{ 'Age' => 22, 'Position' => { 'Rank' => 1 } }, '/data2', 'write'] => true,
|
272
|
+
[{ 'Age' => 62, 'Position' => { 'Rank' => 1 } }, '/data2', 'read'] => false,
|
273
|
+
|
274
|
+
[{ 'Age' => 22, 'Position' => { 'Rank' => 1 } }, '/data3', 'read'] => false,
|
275
|
+
|
276
|
+
[{ 'Age' => 22, 'Position' => { 'Rank' => 1 } }, '/special_data', 'read'] => false,
|
277
|
+
[{ 'Age' => 22, 'Position' => { 'Rank' => 2 } }, '/special_data', 'read'] => true
|
278
|
+
}
|
279
|
+
|
280
|
+
it_behaves_like 'correctly enforces rules', requests
|
281
|
+
end
|
282
|
+
|
283
|
+
context 'with REST' do
|
284
|
+
let(:model) { model_config 'rest' }
|
285
|
+
let(:adapter) { policy_file 'rest' }
|
286
|
+
|
287
|
+
requests = {
|
288
|
+
%w[alice /alice_data/item GET] => true,
|
289
|
+
%w[alice /alice_data/item POST] => false,
|
290
|
+
%w[alice /alice_data/resource1 GET] => true,
|
291
|
+
%w[alice /alice_data/resource1 POST] => true,
|
292
|
+
%w[alice /cathy_data/item PUT] => false,
|
293
|
+
|
294
|
+
%w[bob /alice_data/resource1 GET] => false,
|
295
|
+
%w[bob /alice_data/resource2 GET] => true,
|
296
|
+
%w[bob /alice_data/resource2 POST] => false,
|
297
|
+
%w[bob /bob_data/resource DELETE] => false,
|
298
|
+
%w[bob /bob_data/resource POST] => true,
|
299
|
+
|
300
|
+
%w[cathy /cathy_data GET] => true,
|
301
|
+
%w[cathy /cathy_data POST] => true,
|
302
|
+
%w[cathy /cathy_data DELETE] => false,
|
303
|
+
%w[cathy /cathy_data/resource GET] => false,
|
304
|
+
%w[cathy /alice_data/resource1 GET] => false
|
305
|
+
}
|
306
|
+
|
307
|
+
it_behaves_like 'correctly enforces rules', requests
|
308
|
+
end
|
309
|
+
|
310
|
+
context 'with REST (keyMatch2)' do
|
311
|
+
let(:model) { model_config 'rest2' }
|
312
|
+
let(:adapter) { policy_file 'rest2' }
|
313
|
+
|
314
|
+
requests = {
|
315
|
+
%w[alice /alice_data/hello GET] => true,
|
316
|
+
%w[alice /alice_data/other_hello GET] => true,
|
317
|
+
%w[alice /alice_data/hello POST] => false,
|
318
|
+
%w[bob /alice_data/hello GET] => false,
|
319
|
+
%w[alice /alice_data2/hello GET] => false,
|
320
|
+
|
321
|
+
%w[alice /alice_data2/1/using/some GET] => true,
|
322
|
+
%w[alice /alice_data2/1/using/some POST] => false,
|
323
|
+
%w[bob /alice_data2/1/using/some GET] => false,
|
324
|
+
%w[alice /alice_data2/1//some GET] => false,
|
325
|
+
%w[alice /alice_data2/1/some GET] => false
|
326
|
+
}
|
327
|
+
|
328
|
+
it_behaves_like 'correctly enforces rules', requests
|
329
|
+
end
|
330
|
+
|
331
|
+
context 'with deny-override' do
|
332
|
+
let(:model) { model_config 'deny_override' }
|
333
|
+
let(:adapter) { policy_file 'deny_override' }
|
334
|
+
|
335
|
+
requests = {
|
336
|
+
%w[alice data1 read] => true,
|
337
|
+
%w[alice data1 write] => true,
|
338
|
+
%w[alice data2 read] => true,
|
339
|
+
%w[alice data2 write] => false,
|
340
|
+
%w[alice data3 read] => true,
|
341
|
+
%w[alice data3 write] => true,
|
342
|
+
|
343
|
+
%w[bob data1 read] => true,
|
344
|
+
%w[bob data1 write] => true,
|
345
|
+
%w[bob data2 read] => true,
|
346
|
+
%w[bob data2 write] => true,
|
347
|
+
%w[bob data3 read] => true,
|
348
|
+
%w[bob data3 write] => true
|
349
|
+
}
|
350
|
+
|
351
|
+
it_behaves_like 'correctly enforces rules', requests
|
352
|
+
end
|
353
|
+
|
354
|
+
context 'with allow-and-deny' do
|
355
|
+
let(:model) { model_config 'allow_and_deny' }
|
356
|
+
let(:adapter) { policy_file 'allow_and_deny' }
|
357
|
+
|
358
|
+
requests = {
|
359
|
+
%w[alice data1 read] => true,
|
360
|
+
%w[alice data1 write] => false,
|
361
|
+
%w[alice data2 read] => true,
|
362
|
+
%w[alice data2 write] => false,
|
363
|
+
%w[alice data3 read] => false,
|
364
|
+
%w[alice data3 write] => false,
|
365
|
+
|
366
|
+
%w[bob data1 read] => false,
|
367
|
+
%w[bob data1 write] => false,
|
368
|
+
%w[bob data2 read] => false,
|
369
|
+
%w[bob data2 write] => true,
|
370
|
+
%w[bob data3 read] => false,
|
371
|
+
%w[bob data3 write] => false
|
372
|
+
}
|
373
|
+
|
374
|
+
it_behaves_like 'correctly enforces rules', requests
|
375
|
+
end
|
376
|
+
|
377
|
+
context 'with implicit priority' do
|
378
|
+
let(:model) { model_config 'priorities/implicit' }
|
379
|
+
let(:adapter) { policy_file 'priorities/implicit' }
|
380
|
+
|
381
|
+
requests = {
|
382
|
+
%w[admin data1 read] => true,
|
383
|
+
%w[admin data2 read] => false
|
384
|
+
}
|
385
|
+
|
386
|
+
it_behaves_like 'correctly enforces rules', requests
|
387
|
+
end
|
388
|
+
|
389
|
+
# This does not implemented in Python version. Examples was taken from here:
|
390
|
+
# https://casbin.org/docs/en/priority-model#load-policy-with-priority-explicitly
|
391
|
+
#
|
392
|
+
# Related PR in Golang version - https://github.com/casbin/casbin/pull/714/files
|
393
|
+
# (we should add sorting by `p_priority` after policy loading).
|
394
|
+
xcontext 'with explicit priority' do
|
395
|
+
let(:model) { model_config 'priorities/explicit' }
|
396
|
+
let(:adapter) { policy_file 'priorities/explicit' }
|
397
|
+
|
398
|
+
requests = {
|
399
|
+
%w[alice data1 write] => true,
|
400
|
+
%w[bob data2 read] => false,
|
401
|
+
%w[bob data2 write] => true
|
402
|
+
}
|
403
|
+
|
404
|
+
it_behaves_like 'correctly enforces rules', requests
|
405
|
+
end
|
406
|
+
|
407
|
+
context 'with IP matching' do
|
408
|
+
let(:model) { model_config 'ip' }
|
409
|
+
let(:adapter) { policy_file 'ip' }
|
410
|
+
|
411
|
+
requests = {
|
412
|
+
%w[192.168.2.1 data1 read] => true,
|
413
|
+
%w[192.168.2.101 data1 read] => true,
|
414
|
+
%w[192.168.1.1 data1 read] => false,
|
415
|
+
%w[192.168.2.101 data1 write] => false,
|
416
|
+
%w[192.168.2.1 data2 read] => false,
|
417
|
+
|
418
|
+
%w[10.0.2.3 data2 write] => true,
|
419
|
+
%w[10.0.5.5 data2 write] => true,
|
420
|
+
%w[10.0.5.5 data2 read] => false,
|
421
|
+
%w[10.1.5.5 data2 write] => false,
|
422
|
+
%w[10.0.5.5 data1 read] => false
|
423
|
+
}
|
424
|
+
|
425
|
+
it_behaves_like 'correctly enforces rules', requests
|
426
|
+
end
|
427
|
+
|
428
|
+
context 'with glob' do
|
429
|
+
let(:model) { model_config 'glob' }
|
430
|
+
let(:adapter) { policy_file 'glob' }
|
431
|
+
|
432
|
+
requests = {
|
433
|
+
%w[u1 /foo/1 read] => true,
|
434
|
+
%w[u1 /foo/1/2 read] => false,
|
435
|
+
%w[u1 /foobar read] => false,
|
436
|
+
%w[u1 /some/foo/1 read] => false,
|
437
|
+
%w[u1 other read] => false,
|
438
|
+
%w[u1 /foo/1 write] => false,
|
439
|
+
|
440
|
+
%w[u2 /foo/1 read] => false,
|
441
|
+
%w[u2 /foo/1/2 read] => false,
|
442
|
+
%w[u2 /foobar read] => true,
|
443
|
+
%w[u2 /some/foo/1 read] => false,
|
444
|
+
%w[u2 other read] => false,
|
445
|
+
%w[u2 /foo/1 write] => false,
|
446
|
+
|
447
|
+
%w[u3 /foo/1 read] => false,
|
448
|
+
%w[u3 /foo/1/2 read] => false,
|
449
|
+
%w[u3 /foobar read] => false,
|
450
|
+
%w[u3 /some/foo/1 read] => true,
|
451
|
+
%w[u3 other read] => false,
|
452
|
+
%w[u3 /foo/1 write] => false,
|
453
|
+
|
454
|
+
%w[u4 /foo/1 read] => false,
|
455
|
+
%w[u4 /foo/1/2 read] => false,
|
456
|
+
%w[u4 /foobar read] => false,
|
457
|
+
%w[u4 /some/foo/1 read] => false,
|
458
|
+
%w[u4 other read] => true,
|
459
|
+
%w[u4 /foo/1 write] => false
|
460
|
+
|
461
|
+
# It seems that `**` does not work properly (the behaviour is different from Golang version)
|
462
|
+
# %w[u5 /foo/1 read] => true,
|
463
|
+
# %w[u5 /foo/1/2 read] => true,
|
464
|
+
# %w[u5 /foobar read] => false,
|
465
|
+
# %w[u5 /some/foo/1 read] => false,
|
466
|
+
# %w[u5 other read] => false,
|
467
|
+
# %w[u5 /foo/1 write] => false
|
468
|
+
}
|
469
|
+
|
470
|
+
it_behaves_like 'correctly enforces rules', requests
|
471
|
+
end
|
472
|
+
end
|
473
|
+
end
|