feat: support Casbin FilteredAdapter interface
fix: add property fix: include necessary class fix: add support for invalid filter type fix: use try catch to invalid filter type
This commit is contained in:
parent
bb566321bb
commit
eebf5bd5eb
|
@ -8,18 +8,26 @@ use Lauthz\Models\Rule;
|
|||
use Lauthz\Contracts\DatabaseAdapter as DatabaseAdapterContract;
|
||||
use Lauthz\Contracts\BatchDatabaseAdapter as BatchDatabaseAdapterContract;
|
||||
use Lauthz\Contracts\UpdatableDatabaseAdapter as UpdatableDatabaseAdapterContract;
|
||||
use Lauthz\Contracts\FilteredDatabaseAdapter as FilteredDatabaseAdapterContract;
|
||||
use Casbin\Persist\Adapters\Filter;
|
||||
use Casbin\Model\Model;
|
||||
use Casbin\Persist\AdapterHelper;
|
||||
use DateTime;
|
||||
use Casbin\Exceptions\InvalidFilterTypeException;
|
||||
/**
|
||||
* DatabaseAdapter.
|
||||
*
|
||||
* @author techlee@qq.com
|
||||
*/
|
||||
class DatabaseAdapter implements DatabaseAdapterContract, BatchDatabaseAdapterContract, UpdatableDatabaseAdapterContract
|
||||
class DatabaseAdapter implements DatabaseAdapterContract, BatchDatabaseAdapterContract, UpdatableDatabaseAdapterContract, FilteredDatabaseAdapterContract
|
||||
{
|
||||
use AdapterHelper;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $filtered = false;
|
||||
|
||||
/**
|
||||
* Rules eloquent model.
|
||||
*
|
||||
|
@ -232,4 +240,59 @@ class DatabaseAdapter implements DatabaseAdapterContract, BatchDatabaseAdapterCo
|
|||
}
|
||||
$instance->update($update);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads only policy rules that match the filter.
|
||||
*
|
||||
* @param Model $model
|
||||
* @param mixed $filter
|
||||
*/
|
||||
public function loadFilteredPolicy(Model $model, $filter): void
|
||||
{
|
||||
$instance = $this->eloquent;
|
||||
|
||||
if (is_string($filter)) {
|
||||
$filter = str_replace(' ', '', $filter);
|
||||
$filter = explode('=', $filter);
|
||||
$instance = $instance->where($filter[0], $filter[1]);
|
||||
} else if ($filter instanceof Filter) {
|
||||
foreach($filter->p as $k => $v) {
|
||||
$where[$v] = $filter->g[$k];
|
||||
$instance = $instance->where($v, $filter->g[$k]);
|
||||
}
|
||||
} else if ($filter instanceof \Closure) {
|
||||
$filter($instance);
|
||||
} else {
|
||||
throw new InvalidFilterTypeException('invalid filter type');
|
||||
}
|
||||
$rows = $instance->get()->makeHidden(['created_at','updated_at', 'id'])->toArray();
|
||||
foreach ($rows as $row) {
|
||||
$row = array_filter($row, function($value) { return !is_null($value) && $value !== ''; });
|
||||
$line = implode(', ', array_filter($row, function ($val) {
|
||||
return '' != $val && !is_null($val);
|
||||
}));
|
||||
$this->loadPolicyLine(trim($line), $model);
|
||||
}
|
||||
$this->setFiltered(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the loaded policy has been filtered.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isFiltered(): bool
|
||||
{
|
||||
return $this->filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets filtered parameter.
|
||||
*
|
||||
* @param bool $filtered
|
||||
*/
|
||||
public function setFiltered(bool $filtered): void
|
||||
{
|
||||
$this->filtered = $filtered;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
|
||||
namespace Lauthz\Contracts;
|
||||
|
||||
use Casbin\Persist\FilteredAdapter;
|
||||
|
||||
interface FilteredDatabaseAdapter extends FilteredAdapter
|
||||
{
|
||||
}
|
|
@ -4,7 +4,9 @@ namespace Lauthz\Tests;
|
|||
|
||||
use Enforcer;
|
||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||
|
||||
use Casbin\Persist\Adapters\Filter;
|
||||
use Lauthz\Models\Rule;
|
||||
use Casbin\Exceptions\InvalidFilterTypeException;
|
||||
class DatabaseAdapterTest extends TestCase
|
||||
{
|
||||
use DatabaseMigrations;
|
||||
|
@ -128,4 +130,48 @@ class DatabaseAdapterTest extends TestCase
|
|||
['data2_admin', 'data2', 'write'],
|
||||
], Enforcer::getPolicy());
|
||||
}
|
||||
|
||||
public function testLoadFilteredPolicy()
|
||||
{
|
||||
$this->initTable();
|
||||
Enforcer::clearPolicy();
|
||||
$this->initConfig();
|
||||
$adapter = Enforcer::getAdapter();
|
||||
$adapter->setFiltered(true);
|
||||
$this->assertEquals([], Enforcer::getPolicy());
|
||||
|
||||
// invalid filter type
|
||||
try {
|
||||
$filter = ['alice', 'data1', 'read'];
|
||||
Enforcer::loadFilteredPolicy($filter);
|
||||
$e = InvalidFilterTypeException::class;
|
||||
$this->fail("Expected exception $e not thrown");
|
||||
} catch (InvalidFilterTypeException $e) {
|
||||
$this->assertEquals("invalid filter type", $e->getMessage());
|
||||
}
|
||||
|
||||
// string
|
||||
$filter = "v0 = bob";
|
||||
Enforcer::loadFilteredPolicy($filter);
|
||||
$this->assertEquals([
|
||||
['bob', 'data2', 'write']
|
||||
], Enforcer::getPolicy());
|
||||
|
||||
// Filter
|
||||
$filter = new Filter(['v2'], ['read']);
|
||||
Enforcer::loadFilteredPolicy($filter);
|
||||
$this->assertEquals([
|
||||
['alice', 'data1', 'read'],
|
||||
['data2_admin', 'data2', 'read'],
|
||||
], Enforcer::getPolicy());
|
||||
|
||||
// Closure
|
||||
Enforcer::loadFilteredPolicy(function (Rule &$rule) {
|
||||
$rule = $rule->where('v1', 'data1');
|
||||
});
|
||||
|
||||
$this->assertEquals([
|
||||
['alice', 'data1', 'read'],
|
||||
], Enforcer::getPolicy());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue