Skip to content

Commit f8c6a13

Browse files
authored
feat: support updateFilteredPolicies method, fix #28 (#29)
feat: support updateFilteredPolicies method, fix #28
1 parent b95ae29 commit f8c6a13

File tree

2 files changed

+178
-0
lines changed

2 files changed

+178
-0
lines changed

src/adapter/DatabaseAdapter.php

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,55 @@ public function updatePolicies(string $sec, string $ptype, array $oldRules, arra
247247
});
248248
}
249249

250+
/**
251+
* UpdateFilteredPolicies deletes old rules and adds new rules.
252+
*
253+
* @param string $sec
254+
* @param string $ptype
255+
* @param array $newPolicies
256+
* @param integer $fieldIndex
257+
* @param string ...$fieldValues
258+
* @return array
259+
*/
260+
public function updateFilteredPolicies(string $sec, string $ptype, array $newPolicies, int $fieldIndex, string ...$fieldValues): array
261+
{
262+
$where['ptype'] = $ptype;
263+
foreach ($fieldValues as $fieldValue) {
264+
$suffix = $fieldIndex++;
265+
if (!is_null($fieldValue) && $fieldValue !== '') {
266+
$where['v'. $suffix] = $fieldValue;
267+
}
268+
}
269+
270+
$newP = [];
271+
$oldP = [];
272+
foreach ($newPolicies as $newRule) {
273+
$col['ptype'] = $ptype;
274+
foreach ($newRule as $key => $value) {
275+
$col['v' . strval($key)] = $value;
276+
}
277+
$newP[] = $col;
278+
}
279+
280+
DB::transaction(function () use ($newP, $where, &$oldP) {
281+
$oldRules = $this->model->where($where);
282+
$oldP = $oldRules->select()->hidden(['id'])->toArray();
283+
284+
foreach ($oldP as &$item) {
285+
$item = array_filter($item, function ($value) {
286+
return !is_null($value) && $value !== '';
287+
});
288+
unset($item['ptype']);
289+
}
290+
291+
$oldRules->delete();
292+
$this->model->insertAll($newP);
293+
});
294+
295+
// return deleted rules
296+
return $oldP;
297+
}
298+
250299
/**
251300
* Returns true if the loaded policy has been filtered.
252301
*

tests/DatabaseAdapterTest.php

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,135 @@ public function testUpdatePolicies()
176176
});
177177
}
178178

179+
public function arrayEqualsWithoutOrder(array $expected, array $actual)
180+
{
181+
if (method_exists($this, 'assertEqualsCanonicalizing')) {
182+
$this->assertEqualsCanonicalizing($expected, $actual);
183+
} else {
184+
array_multisort($expected);
185+
array_multisort($actual);
186+
$this->assertEquals($expected, $actual);
187+
}
188+
}
189+
190+
public function testUpdateFilteredPolicies()
191+
{
192+
$this->testing(function () {
193+
$this->assertEquals([
194+
['alice', 'data1', 'read'],
195+
['bob', 'data2', 'write'],
196+
['data2_admin', 'data2', 'read'],
197+
['data2_admin', 'data2', 'write'],
198+
], Enforcer::getPolicy());
199+
200+
Enforcer::updateFilteredPolicies([["alice", "data1", "write"]], 0, "alice", "data1", "read");
201+
Enforcer::updateFilteredPolicies([["bob", "data2", "read"]], 0, "bob", "data2", "write");
202+
203+
$policies = [
204+
['alice', 'data1', 'write'],
205+
['bob', 'data2', 'read'],
206+
['data2_admin', 'data2', 'read'],
207+
['data2_admin', 'data2', 'write']
208+
];
209+
210+
$this->arrayEqualsWithoutOrder($policies, Enforcer::getPolicy());
211+
212+
// test use updateFilteredPolicies to update all policies of a user
213+
$this->initTable();
214+
Enforcer::loadPolicy();
215+
$policies = [
216+
['alice', 'data2', 'write'],
217+
['bob', 'data1', 'read']
218+
];
219+
Enforcer::addPolicies($policies);
220+
221+
$this->arrayEqualsWithoutOrder([
222+
['alice', 'data1', 'read'],
223+
['bob', 'data2', 'write'],
224+
['data2_admin', 'data2', 'read'],
225+
['data2_admin', 'data2', 'write'],
226+
['alice', 'data2', 'write'],
227+
['bob', 'data1', 'read']
228+
], Enforcer::getPolicy());
229+
230+
Enforcer::updateFilteredPolicies([['alice', 'data1', 'write'], ['alice', 'data2', 'read']], 0, 'alice');
231+
Enforcer::updateFilteredPolicies([['bob', 'data1', 'write'], ["bob", "data2", "read"]], 0, 'bob');
232+
233+
$policies = [
234+
['alice', 'data1', 'write'],
235+
['alice', 'data2', 'read'],
236+
['bob', 'data1', 'write'],
237+
['bob', 'data2', 'read'],
238+
['data2_admin', 'data2', 'read'],
239+
['data2_admin', 'data2', 'write']
240+
];
241+
242+
$this->arrayEqualsWithoutOrder($policies, Enforcer::getPolicy());
243+
244+
// test if $fieldValues contains empty string
245+
$this->initTable();
246+
Enforcer::loadPolicy();
247+
$policies = [
248+
['alice', 'data2', 'write'],
249+
['bob', 'data1', 'read']
250+
];
251+
Enforcer::addPolicies($policies);
252+
253+
$this->assertEquals([
254+
['alice', 'data1', 'read'],
255+
['bob', 'data2', 'write'],
256+
['data2_admin', 'data2', 'read'],
257+
['data2_admin', 'data2', 'write'],
258+
['alice', 'data2', 'write'],
259+
['bob', 'data1', 'read']
260+
], Enforcer::getPolicy());
261+
262+
Enforcer::updateFilteredPolicies([['alice', 'data1', 'write'], ['alice', 'data2', 'read']], 0, 'alice', '', '');
263+
Enforcer::updateFilteredPolicies([['bob', 'data1', 'write'], ["bob", "data2", "read"]], 0, 'bob', '', '');
264+
265+
$policies = [
266+
['alice', 'data1', 'write'],
267+
['alice', 'data2', 'read'],
268+
['bob', 'data1', 'write'],
269+
['bob', 'data2', 'read'],
270+
['data2_admin', 'data2', 'read'],
271+
['data2_admin', 'data2', 'write']
272+
];
273+
274+
$this->arrayEqualsWithoutOrder($policies, Enforcer::getPolicy());
275+
276+
// test if $fieldIndex is not zero
277+
$this->initTable();
278+
Enforcer::loadPolicy();
279+
$policies = [
280+
['alice', 'data2', 'write'],
281+
['bob', 'data1', 'read']
282+
];
283+
Enforcer::addPolicies($policies);
284+
285+
$this->assertEquals([
286+
['alice', 'data1', 'read'],
287+
['bob', 'data2', 'write'],
288+
['data2_admin', 'data2', 'read'],
289+
['data2_admin', 'data2', 'write'],
290+
['alice', 'data2', 'write'],
291+
['bob', 'data1', 'read']
292+
], Enforcer::getPolicy());
293+
294+
Enforcer::updateFilteredPolicies([['alice', 'data1', 'edit'], ['bob', 'data1', 'edit']], 2, 'read');
295+
Enforcer::updateFilteredPolicies([['alice', 'data2', 'read'], ["bob", "data2", "read"]], 2, 'write');
296+
297+
$policies = [
298+
['alice', 'data1', 'edit'],
299+
['alice', 'data2', 'read'],
300+
['bob', 'data1', 'edit'],
301+
['bob', 'data2', 'read'],
302+
];
303+
304+
$this->arrayEqualsWithoutOrder($policies, Enforcer::getPolicy());
305+
});
306+
}
307+
179308
public function testLoadFilteredPolicy()
180309
{
181310
$this->testing(function () {

0 commit comments

Comments
 (0)