Skip to content

Commit 4a23074

Browse files
leeqvipbasakest
andauthoredSep 3, 2021
feat: support updateFilteredPolicies method (#17)
* feat: support updateFilteredPolicies method (#16) * fix: errors in updateFilteredPolicies Co-authored-by: basakest <47746206+basakest@users.noreply.github.com>
1 parent 322f077 commit 4a23074

File tree

3 files changed

+192
-1
lines changed

3 files changed

+192
-1
lines changed
 

‎.gitignore

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,6 @@ composer.lock
66
*.iml
77

88
# coverage report
9-
/build
9+
/build
10+
11+
.phpunit.*

‎src/Adapter.php

+64
Original file line numberDiff line numberDiff line change
@@ -328,4 +328,68 @@ public function updatePolicies(string $sec, string $ptype, array $oldRules, arra
328328
throw $e;
329329
}
330330
}
331+
332+
/**
333+
* UpdateFilteredPolicies deletes old rules and adds new rules.
334+
*
335+
* @param string $sec
336+
* @param string $ptype
337+
* @param array $newPolicies
338+
* @param integer $fieldIndex
339+
* @param string ...$fieldValues
340+
* @return array
341+
*/
342+
public function updateFilteredPolicies(string $sec, string $ptype, array $newPolicies, int $fieldIndex, string ...$fieldValues): array
343+
{
344+
$deleteWhere['ptype'] = $ptype;
345+
$deleteCondition[] = 'ptype = :ptype';
346+
foreach ($fieldValues as $value) {
347+
$key = $fieldIndex++;
348+
if (!is_null($value) && $value !== '') {
349+
$placeholder = "v" . strval($key);
350+
$deleteWhere['v' . strval($key)] = $value;
351+
$deleteCondition[] = 'v' . strval($key) . ' = :' . $placeholder;
352+
}
353+
}
354+
$deleteSql = "DELETE FROM {$this->casbinRuleTableName} WHERE " . implode(' AND ', $deleteCondition);
355+
356+
$selectSql = "SELECT * FROM {$this->casbinRuleTableName} WHERE " . implode(' AND ', $deleteCondition);
357+
$oldP = $this->connection->query($selectSql, $deleteWhere);
358+
foreach ($oldP as &$item) {
359+
$item = array_filter($item, function ($value) {
360+
return !is_null($value) && $value !== '';
361+
});
362+
unset($item['ptype']);
363+
unset($item['id']);
364+
}
365+
366+
$columns = ['ptype', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5'];
367+
$values = [];
368+
$sets = [];
369+
$columnsCount = count($columns);
370+
foreach ($newPolicies as $newPolicy) {
371+
array_unshift($newPolicy, $ptype);
372+
$values = array_merge($values, array_pad($newPolicy, $columnsCount, null));
373+
$sets[] = array_pad([], $columnsCount, '?');
374+
}
375+
$valuesStr = implode(', ', array_map(function ($set) {
376+
return '(' . implode(', ', $set) . ')';
377+
}, $sets));
378+
$insertSql = 'INSERT INTO ' . $this->casbinRuleTableName . ' (' . implode(', ', $columns) . ')' . ' VALUES ' . $valuesStr;
379+
380+
// start transaction
381+
$this->connection->getPdo()->beginTransaction();
382+
try {
383+
// delete old data
384+
$this->connection->execute($deleteSql, $deleteWhere);
385+
// insert new data
386+
$this->connection->execute($insertSql, $values);
387+
$this->connection->getPdo()->commit();
388+
} catch (Throwable $e) {
389+
$this->connection->getPdo()->rollback();
390+
throw $e;
391+
}
392+
393+
return $oldP;
394+
}
331395
}

‎tests/AdapterTest.php

+125
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,131 @@ public function testUpdatePolicies()
273273
], $e->getPolicy());
274274
}
275275

276+
public function arrayEqualsWithoutOrder(array $expected, array $actual)
277+
{
278+
if (method_exists($this, 'assertEqualsCanonicalizing')) {
279+
$this->assertEqualsCanonicalizing($expected, $actual);
280+
} else {
281+
array_multisort($expected);
282+
array_multisort($actual);
283+
$this->assertEquals($expected, $actual);
284+
}
285+
}
286+
287+
public function testUpdateFilteredPolicies()
288+
{
289+
$e = $this->getEnforcer();
290+
$this->assertEquals([
291+
['alice', 'data1', 'read'],
292+
['bob', 'data2', 'write'],
293+
['data2_admin', 'data2', 'read'],
294+
['data2_admin', 'data2', 'write'],
295+
], $e->getPolicy());
296+
297+
$e->updateFilteredPolicies([["alice", "data1", "write"]], 0, "alice", "data1", "read");
298+
$e->updateFilteredPolicies([["bob", "data2", "read"]], 0, "bob", "data2", "write");
299+
300+
$policies = [
301+
['alice', 'data1', 'write'],
302+
['bob', 'data2', 'read'],
303+
['data2_admin', 'data2', 'read'],
304+
['data2_admin', 'data2', 'write']
305+
];
306+
307+
$this->arrayEqualsWithoutOrder($policies, $e->getPolicy());
308+
309+
// test use updateFilteredPolicies to update all policies of a user
310+
$e = $this->getEnforcer();
311+
$policies = [
312+
['alice', 'data2', 'write'],
313+
['bob', 'data1', 'read']
314+
];
315+
$e->addPolicies($policies);
316+
317+
$this->arrayEqualsWithoutOrder([
318+
['alice', 'data1', 'read'],
319+
['bob', 'data2', 'write'],
320+
['data2_admin', 'data2', 'read'],
321+
['data2_admin', 'data2', 'write'],
322+
['alice', 'data2', 'write'],
323+
['bob', 'data1', 'read']
324+
], $e->getPolicy());
325+
326+
$e->updateFilteredPolicies([['alice', 'data1', 'write'], ['alice', 'data2', 'read']], 0, 'alice');
327+
$e->updateFilteredPolicies([['bob', 'data1', 'write'], ["bob", "data2", "read"]], 0, 'bob');
328+
329+
$policies = [
330+
['alice', 'data1', 'write'],
331+
['alice', 'data2', 'read'],
332+
['bob', 'data1', 'write'],
333+
['bob', 'data2', 'read'],
334+
['data2_admin', 'data2', 'read'],
335+
['data2_admin', 'data2', 'write']
336+
];
337+
338+
$this->arrayEqualsWithoutOrder($policies, $e->getPolicy());
339+
340+
// test if $fieldValues contains empty string
341+
$e = $this->getEnforcer();
342+
$policies = [
343+
['alice', 'data2', 'write'],
344+
['bob', 'data1', 'read']
345+
];
346+
$e->addPolicies($policies);
347+
348+
$this->assertEquals([
349+
['alice', 'data1', 'read'],
350+
['bob', 'data2', 'write'],
351+
['data2_admin', 'data2', 'read'],
352+
['data2_admin', 'data2', 'write'],
353+
['alice', 'data2', 'write'],
354+
['bob', 'data1', 'read']
355+
], $e->getPolicy());
356+
357+
$e->updateFilteredPolicies([['alice', 'data1', 'write'], ['alice', 'data2', 'read']], 0, 'alice', '', '');
358+
$e->updateFilteredPolicies([['bob', 'data1', 'write'], ["bob", "data2", "read"]], 0, 'bob', '', '');
359+
360+
$policies = [
361+
['alice', 'data1', 'write'],
362+
['alice', 'data2', 'read'],
363+
['bob', 'data1', 'write'],
364+
['bob', 'data2', 'read'],
365+
['data2_admin', 'data2', 'read'],
366+
['data2_admin', 'data2', 'write']
367+
];
368+
369+
$this->arrayEqualsWithoutOrder($policies, $e->getPolicy());
370+
371+
// test if $fieldIndex is not zero
372+
$e = $this->getEnforcer();
373+
$policies = [
374+
['alice', 'data2', 'write'],
375+
['bob', 'data1', 'read']
376+
];
377+
$e->addPolicies($policies);
378+
379+
$this->assertEquals([
380+
['alice', 'data1', 'read'],
381+
['bob', 'data2', 'write'],
382+
['data2_admin', 'data2', 'read'],
383+
['data2_admin', 'data2', 'write'],
384+
['alice', 'data2', 'write'],
385+
['bob', 'data1', 'read']
386+
], $e->getPolicy());
387+
388+
$e->updateFilteredPolicies([['alice', 'data1', 'edit'], ['bob', 'data1', 'edit']], 2, 'read');
389+
$e->updateFilteredPolicies([['alice', 'data2', 'read'], ["bob", "data2", "read"]], 2, 'write');
390+
391+
$policies = [
392+
['alice', 'data1', 'edit'],
393+
['alice', 'data2', 'read'],
394+
['bob', 'data1', 'edit'],
395+
['bob', 'data2', 'read'],
396+
];
397+
398+
$this->arrayEqualsWithoutOrder($policies, $e->getPolicy());
399+
}
400+
276401
protected function env($key, $default = null)
277402
{
278403
$value = getenv($key);

0 commit comments

Comments
 (0)