Skip to content

Commit 63da5ec

Browse files
authored
Merge pull request #5 from basakest/FilterAdapter
try to implement FilterAdapter
2 parents e0355bd + 5eaf0e3 commit 63da5ec

File tree

3 files changed

+152
-1
lines changed

3 files changed

+152
-1
lines changed

Diff for: .travis.yml

+3
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ before_install:
1818
install:
1919
- travis_retry composer install --no-suggest --no-interaction
2020

21+
before_script:
22+
- export XDEBUG_MODE=coverage
23+
2124
script:
2225
- vendor/bin/phpunit --version
2326
- mkdir -p build/logs

Diff for: src/Adapter.php

+87-1
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,58 @@
66
use Casbin\Persist\Adapter as AdapterContract;
77
use TechOne\Database\Manager;
88
use Casbin\Persist\AdapterHelper;
9+
use Casbin\Persist\FilteredAdapter;
10+
use Casbin\Persist\Adapters\Filter;
11+
use Casbin\Exceptions\InvalidFilterTypeException;
12+
use Closure;
913

1014
/**
1115
* DatabaseAdapter.
1216
*
1317
1418
*/
15-
class Adapter implements AdapterContract
19+
class Adapter implements AdapterContract, FilteredAdapter
1620
{
1721
use AdapterHelper;
1822

1923
protected $config;
2024

25+
protected $filtered;
26+
2127
protected $connection;
2228

2329
public $casbinRuleTableName = 'casbin_rule';
2430

31+
public $rows = [];
32+
2533
public function __construct(array $config)
2634
{
2735
$this->config = $config;
36+
$this->filtered = false;
2837
$this->connection = (new Manager($config))->getConnection();
2938
$this->initTable();
3039
}
3140

41+
/**
42+
* Returns true if the loaded policy has been filtered.
43+
*
44+
* @return bool
45+
*/
46+
public function isFiltered(): bool
47+
{
48+
return $this->filtered;
49+
}
50+
51+
/**
52+
* Sets filtered parameter.
53+
*
54+
* @param bool $filtered
55+
*/
56+
public function setFiltered(bool $filtered): void
57+
{
58+
$this->filtered = $filtered;
59+
}
60+
3261
public static function newAdapter(array $config)
3362
{
3463
return new static($config);
@@ -154,4 +183,61 @@ public function removeFilteredPolicy(string $sec, string $ptype, int $fieldIndex
154183

155184
$this->connection->execute($sql, $where);
156185
}
186+
187+
/**
188+
* Loads only policy rules that match the filter from storage.
189+
*
190+
* @param Model $model
191+
* @param mixed $filter
192+
*
193+
* @throws CasbinException
194+
*/
195+
public function loadFilteredPolicy(Model $model, $filter): void
196+
{
197+
// if $filter is empty, load all policies
198+
if (is_null($filter)) {
199+
$this->loadPolicy($model);
200+
return;
201+
}
202+
// the basic sql
203+
$sql = 'SELECT ptype, v0, v1, v2, v3, v4, v5 FROM '.$this->casbinRuleTableName . ' WHERE ';
204+
205+
if ($filter instanceof Filter) {
206+
$type = '';
207+
$filter = (array) $filter;
208+
// choose which ptype to use
209+
foreach($filter as $i => $v) {
210+
if (!empty($v)) {
211+
array_unshift($filter[$i], $i);
212+
$type = $i;
213+
break;
214+
}
215+
}
216+
$items = ['ptype', 'v0', 'v1', 'v2', 'v3', 'v4', 'v5'];
217+
$temp = [];
218+
$values = [];
219+
foreach($items as $i => $item) {
220+
if (isset($filter[$type][$i]) && !empty($filter[$type][$i])) {
221+
array_push($temp, $item . '=:' . $item);
222+
$values[$item] = $filter[$type][$i];
223+
}
224+
}
225+
$sql .= implode(' and ', $temp);
226+
$rows = $this->connection->query($sql, $values);
227+
} elseif (is_string($filter)) {
228+
$sql .= $filter;
229+
$rows = $this->connection->query($sql);
230+
} else if ($filter instanceof Closure) {
231+
$filter($this->connection, $sql, $this->rows);
232+
} else {
233+
throw new InvalidFilterTypeException('invalid filter type');
234+
}
235+
236+
$rows = $rows ?? $this->rows;
237+
foreach($rows as $row) {
238+
$line = implode(', ', $row);
239+
$this->loadPolicyLine($line, $model);
240+
}
241+
$this->filtered = true;
242+
}
157243
}

Diff for: tests/AdapterTest.php

+62
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
namespace Tests;
44

55
use Casbin\Enforcer;
6+
use Casbin\Model\Model;
7+
use Casbin\Persist\Adapter;
68
use CasbinAdapter\Database\Adapter as DatabaseAdapter;
79
use PHPUnit\Framework\TestCase;
810
use TechOne\Database\Manager;
11+
use Casbin\Persist\Adapters\Filter;
912

1013
class AdapterTest extends TestCase
1114
{
@@ -44,6 +47,31 @@ protected function getEnforcer()
4447
return new Enforcer(__DIR__.'/rbac_model.conf', $adapter);
4548
}
4649

50+
protected function getEnforcerWithAdapter(Adapter $adapter): Enforcer
51+
{
52+
$this->adapter = $adapter;
53+
$this->initDb($this->adapter);
54+
$model = Model::newModelFromString(
55+
<<<'EOT'
56+
[request_definition]
57+
r = sub, obj, act
58+
59+
[policy_definition]
60+
p = sub, obj, act
61+
62+
[role_definition]
63+
g = _, _
64+
65+
[policy_effect]
66+
e = some(where (p.eft == allow))
67+
68+
[matchers]
69+
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act
70+
EOT
71+
);
72+
return new Enforcer($model, $this->adapter);
73+
}
74+
4775
public function testLoadPolicy()
4876
{
4977
$e = $this->getEnforcer();
@@ -54,6 +82,40 @@ public function testLoadPolicy()
5482
$this->assertTrue($e->enforce('alice', 'data2', 'write'));
5583
}
5684

85+
public function testLoadFilteredPolicy()
86+
{
87+
$this->initConfig();
88+
$adapter = DatabaseAdapter::newAdapter($this->config);
89+
$adapter->setFiltered(true);
90+
$e = $this->getEnforcerWithAdapter($adapter);
91+
$this->assertEquals([], $e->getPolicy());
92+
93+
// string
94+
$filter = "v0 = 'bob'";
95+
$e->loadFilteredPolicy($filter);
96+
$this->assertEquals([
97+
//
98+
['bob', 'data2', 'write', '', '', '']
99+
], $e->getPolicy());
100+
101+
// Filter
102+
$filter = new Filter(['', '', 'read']);
103+
$e->loadFilteredPolicy($filter);
104+
$this->assertEquals([
105+
['alice', 'data1', 'read', '', '', ''],
106+
['data2_admin', 'data2', 'read', '', '', ''],
107+
], $e->getPolicy());
108+
109+
// Closure
110+
$e->loadFilteredPolicy(function ($connection, $sql, &$rows) {
111+
$rows = $connection->query($sql . "v0 = 'alice'");
112+
});
113+
114+
$this->assertEquals([
115+
['alice', 'data1', 'read', '', '', ''],
116+
], $e->getPolicy());
117+
}
118+
57119
public function testAddPolicy()
58120
{
59121
$e = $this->getEnforcer();

0 commit comments

Comments
 (0)