feat: support updateFilteredPolicies method (#29)

feat: support updateFilteredPolicies method
This commit is contained in:
basakest 2021-09-02 12:36:43 +08:00 committed by GitHub
parent 877f2f27b4
commit 9676f0b918
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 176 additions and 0 deletions

View File

@ -15,6 +15,7 @@ use Casbin\Persist\AdapterHelper;
use DateTime; use DateTime;
use Casbin\Exceptions\InvalidFilterTypeException; use Casbin\Exceptions\InvalidFilterTypeException;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
/** /**
* DatabaseAdapter. * DatabaseAdapter.
* *
@ -242,6 +243,54 @@ class DatabaseAdapter implements DatabaseAdapterContract, BatchDatabaseAdapterCo
}); });
} }
/**
* UpdateFilteredPolicies deletes old rules and adds new rules.
*
* @param string $sec
* @param string $ptype
* @param array $newPolicies
* @param integer $fieldIndex
* @param string ...$fieldValues
* @return array
*/
public function updateFilteredPolicies(string $sec, string $ptype, array $newPolicies, int $fieldIndex, string ...$fieldValues): array
{
$where['p_type'] = $ptype;
foreach ($fieldValues as $fieldValue) {
if (!is_null($fieldValue) && $fieldValue !== '') {
$where['v'. $fieldIndex++] = $fieldValue;
}
}
$newP = [];
$oldP = [];
foreach ($newPolicies as $newRule) {
$col['p_type'] = $ptype;
foreach ($newRule as $key => $value) {
$col['v' . strval($key)] = $value;
}
$newP[] = $col;
}
DB::transaction(function () use ($newP, $where, &$oldP) {
$oldRules = $this->eloquent->where($where);
$oldP = $oldRules->get()->makeHidden(['created_at','updated_at', 'id'])->toArray();
foreach ($oldP as &$item) {
$item = array_filter($item, function ($value) {
return !is_null($value) && $value !== '';
});
unset($item['p_type']);
}
$oldRules->delete();
$this->eloquent->create($newP);
});
// return deleted rules
return $oldP;
}
/** /**
* Loads only policy rules that match the filter. * Loads only policy rules that match the filter.
* *

View File

@ -159,6 +159,133 @@ class DatabaseAdapterTest extends TestCase
], Enforcer::getPolicy()); ], Enforcer::getPolicy());
} }
public function arrayEqualsWithoutOrder(array $expected, array $actual)
{
if (method_exists($this, 'assertEqualsCanonicalizing')) {
$this->assertEqualsCanonicalizing($expected, $actual);
} else {
array_multisort($expected);
array_multisort($actual);
$this->assertEquals($expected, $actual);
}
}
public function testUpdateFilteredPolicies()
{
$this->assertEquals([
['alice', 'data1', 'read'],
['bob', 'data2', 'write'],
['data2_admin', 'data2', 'read'],
['data2_admin', 'data2', 'write'],
], Enforcer::getPolicy());
Enforcer::updateFilteredPolicies([["alice", "data1", "write"]], 0, "alice", "data1", "read");
Enforcer::updateFilteredPolicies([["bob", "data2", "read"]], 0, "bob", "data2", "write");
$policies = [
['alice', 'data1', 'write'],
['bob', 'data2', 'read'],
['data2_admin', 'data2', 'read'],
['data2_admin', 'data2', 'write']
];
$this->arrayEqualsWithoutOrder($policies, Enforcer::getPolicy());
// test use updateFilteredPolicies to update all policies of a user
$this->initTable();
Enforcer::loadPolicy();
$policies = [
['alice', 'data2', 'write'],
['bob', 'data1', 'read']
];
Enforcer::addPolicies($policies);
$this->arrayEqualsWithoutOrder([
['alice', 'data1', 'read'],
['bob', 'data2', 'write'],
['data2_admin', 'data2', 'read'],
['data2_admin', 'data2', 'write'],
['alice', 'data2', 'write'],
['bob', 'data1', 'read']
], Enforcer::getPolicy());
Enforcer::updateFilteredPolicies([['alice', 'data1', 'write'], ['alice', 'data2', 'read']], 0, 'alice');
Enforcer::updateFilteredPolicies([['bob', 'data1', 'write'], ["bob", "data2", "read"]], 0, 'bob');
$policies = [
['alice', 'data1', 'write'],
['alice', 'data2', 'read'],
['bob', 'data1', 'write'],
['bob', 'data2', 'read'],
['data2_admin', 'data2', 'read'],
['data2_admin', 'data2', 'write']
];
$this->arrayEqualsWithoutOrder($policies, Enforcer::getPolicy());
// test if $fieldValues contains empty string
$this->initTable();
Enforcer::loadPolicy();
$policies = [
['alice', 'data2', 'write'],
['bob', 'data1', 'read']
];
Enforcer::addPolicies($policies);
$this->assertEquals([
['alice', 'data1', 'read'],
['bob', 'data2', 'write'],
['data2_admin', 'data2', 'read'],
['data2_admin', 'data2', 'write'],
['alice', 'data2', 'write'],
['bob', 'data1', 'read']
], Enforcer::getPolicy());
Enforcer::updateFilteredPolicies([['alice', 'data1', 'write'], ['alice', 'data2', 'read']], 0, 'alice', '', '');
Enforcer::updateFilteredPolicies([['bob', 'data1', 'write'], ["bob", "data2", "read"]], 0, 'bob', '', '');
$policies = [
['alice', 'data1', 'write'],
['alice', 'data2', 'read'],
['bob', 'data1', 'write'],
['bob', 'data2', 'read'],
['data2_admin', 'data2', 'read'],
['data2_admin', 'data2', 'write']
];
$this->arrayEqualsWithoutOrder($policies, Enforcer::getPolicy());
// test if $fieldIndex is not zero
$this->initTable();
Enforcer::loadPolicy();
$policies = [
['alice', 'data2', 'write'],
['bob', 'data1', 'read']
];
Enforcer::addPolicies($policies);
$this->assertEquals([
['alice', 'data1', 'read'],
['bob', 'data2', 'write'],
['data2_admin', 'data2', 'read'],
['data2_admin', 'data2', 'write'],
['alice', 'data2', 'write'],
['bob', 'data1', 'read']
], Enforcer::getPolicy());
Enforcer::updateFilteredPolicies([['alice', 'data1', 'write'], ['bob', 'data1', 'write']], 2, 'read');
Enforcer::updateFilteredPolicies([['alice', 'data2', 'read'], ["bob", "data2", "read"]], 2, 'write');
$policies = [
['alice', 'data1', 'write'],
['alice', 'data2', 'read'],
['bob', 'data1', 'write'],
['bob', 'data2', 'read'],
];
$this->arrayEqualsWithoutOrder($policies, Enforcer::getPolicy());
}
public function testLoadFilteredPolicy() public function testLoadFilteredPolicy()
{ {
$this->initTable(); $this->initTable();