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\DatabaseAdapter as DatabaseAdapterContract;
|
||||||
use Lauthz\Contracts\BatchDatabaseAdapter as BatchDatabaseAdapterContract;
|
use Lauthz\Contracts\BatchDatabaseAdapter as BatchDatabaseAdapterContract;
|
||||||
use Lauthz\Contracts\UpdatableDatabaseAdapter as UpdatableDatabaseAdapterContract;
|
use Lauthz\Contracts\UpdatableDatabaseAdapter as UpdatableDatabaseAdapterContract;
|
||||||
|
use Lauthz\Contracts\FilteredDatabaseAdapter as FilteredDatabaseAdapterContract;
|
||||||
|
use Casbin\Persist\Adapters\Filter;
|
||||||
use Casbin\Model\Model;
|
use Casbin\Model\Model;
|
||||||
use Casbin\Persist\AdapterHelper;
|
use Casbin\Persist\AdapterHelper;
|
||||||
use DateTime;
|
use DateTime;
|
||||||
|
use Casbin\Exceptions\InvalidFilterTypeException;
|
||||||
/**
|
/**
|
||||||
* DatabaseAdapter.
|
* DatabaseAdapter.
|
||||||
*
|
*
|
||||||
* @author techlee@qq.com
|
* @author techlee@qq.com
|
||||||
*/
|
*/
|
||||||
class DatabaseAdapter implements DatabaseAdapterContract, BatchDatabaseAdapterContract, UpdatableDatabaseAdapterContract
|
class DatabaseAdapter implements DatabaseAdapterContract, BatchDatabaseAdapterContract, UpdatableDatabaseAdapterContract, FilteredDatabaseAdapterContract
|
||||||
{
|
{
|
||||||
use AdapterHelper;
|
use AdapterHelper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $filtered = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rules eloquent model.
|
* Rules eloquent model.
|
||||||
*
|
*
|
||||||
|
@ -232,4 +240,59 @@ class DatabaseAdapter implements DatabaseAdapterContract, BatchDatabaseAdapterCo
|
||||||
}
|
}
|
||||||
$instance->update($update);
|
$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 Enforcer;
|
||||||
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
use Illuminate\Foundation\Testing\DatabaseMigrations;
|
||||||
|
use Casbin\Persist\Adapters\Filter;
|
||||||
|
use Lauthz\Models\Rule;
|
||||||
|
use Casbin\Exceptions\InvalidFilterTypeException;
|
||||||
class DatabaseAdapterTest extends TestCase
|
class DatabaseAdapterTest extends TestCase
|
||||||
{
|
{
|
||||||
use DatabaseMigrations;
|
use DatabaseMigrations;
|
||||||
|
@ -128,4 +130,48 @@ class DatabaseAdapterTest extends TestCase
|
||||||
['data2_admin', 'data2', 'write'],
|
['data2_admin', 'data2', 'write'],
|
||||||
], Enforcer::getPolicy());
|
], 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