Skip to content

Commit 589472b

Browse files
authored
Merge pull request #13 from basakest/FilteredAdapter
feat: support Casbin FilteredAdapter interface
2 parents 83ac41c + 0bf7441 commit 589472b

File tree

2 files changed

+114
-2
lines changed

2 files changed

+114
-2
lines changed

src/Adapters/DatabaseAdapter.php

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,19 @@
1212
use EasySwoole\Permission\Model\RulesModel;
1313
use Throwable;
1414
use Casbin\Persist\BatchAdapter;
15+
use Casbin\Persist\FilteredAdapter;
16+
use Casbin\Persist\Adapters\Filter;
17+
use Casbin\Exceptions\InvalidFilterTypeException;
1518

16-
class DatabaseAdapter implements Adapter, BatchAdapter
19+
class DatabaseAdapter implements Adapter, BatchAdapter, FilteredAdapter
1720
{
1821
use AdapterHelper;
1922

23+
/**
24+
* @var bool
25+
*/
26+
private $filtered = false;
27+
2028
/**
2129
* savePolicyLine function.
2230
*
@@ -182,7 +190,7 @@ public function addPolicies(string $sec, string $ptype, array $rules): void
182190
public function removePolicies(string $sec, string $ptype, array $rules): void
183191
{
184192
$ids = [];
185-
193+
186194
foreach($rules as $rule) {
187195
$where = [];
188196
$where['ptype'] = $ptype;
@@ -195,4 +203,62 @@ public function removePolicies(string $sec, string $ptype, array $rules): void
195203

196204
RulesModel::create()->destroy($ids);
197205
}
206+
207+
/**
208+
* loads only policy rules that match the filter.
209+
*
210+
* @param Model $model
211+
* @param mixed $filter
212+
*/
213+
public function loadFilteredPolicy(Model $model, $filter): void
214+
{
215+
$instance = RulesModel::create();
216+
217+
if (is_string($filter)) {
218+
$filter = str_replace(' ', '', $filter);
219+
$filter = explode('=', $filter);
220+
$instance->where($filter[0], $filter[1]);
221+
} else if ($filter instanceof Filter) {
222+
foreach($filter->p as $k => $v) {
223+
$where[$v] = $filter->g[$k];
224+
$instance->where($v, $filter->g[$k]);
225+
}
226+
} else if ($filter instanceof \Closure) {
227+
$instance->where($filter);
228+
} else {
229+
throw new InvalidFilterTypeException('invalid filter type');
230+
}
231+
$rows = $instance->all();
232+
//var_dump($rows);
233+
foreach ($rows as $row) {
234+
$row = $row->hidden(['create_time','update_time', 'id'])->toArray();
235+
$row = array_filter($row, function($value) { return !is_null($value) && $value !== ''; });
236+
//var_dump($row);
237+
$line = implode(', ', array_filter($row, function ($val) {
238+
return '' != $val && !is_null($val);
239+
}));
240+
$this->loadPolicyLine(trim($line), $model);
241+
}
242+
$this->setFiltered(true);
243+
}
244+
245+
/**
246+
* Returns true if the loaded policy has been filtered.
247+
*
248+
* @return bool
249+
*/
250+
public function isFiltered(): bool
251+
{
252+
return $this->filtered;
253+
}
254+
255+
/**
256+
* Sets filtered parameter.
257+
*
258+
* @param bool $filtered
259+
*/
260+
public function setFiltered(bool $filtered): void
261+
{
262+
$this->filtered = $filtered;
263+
}
198264
}

tests/DatabaseAdapterTest.php

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
use EasySwoole\Permission\Config;
1010
use EasySwoole\ORM\Db\Connection;
1111
use EasySwoole\EasySwoole\Config as ESConfig;
12+
use Casbin\Exceptions\InvalidFilterTypeException;
13+
use Casbin\Persist\Adapters\Filter;
1214

1315
class DatabaseAdapterTest extends TestCase
1416
{
@@ -143,4 +145,48 @@ public function testRemovePolicies()
143145
['bob', 'data2', 'write']
144146
], $e->getPolicy());
145147
}
148+
149+
public function testLoadFilteredPolicy()
150+
{
151+
$e = $this->getEnforcer();
152+
$e->clearPolicy();
153+
$this->initConfig();
154+
$adapter = $e->getAdapter();
155+
$adapter->setFiltered(true);
156+
$this->assertEquals([], $e->getPolicy());
157+
158+
// invalid filter type
159+
try {
160+
$filter = ['alice', 'data1', 'read'];
161+
$e->loadFilteredPolicy($filter);
162+
$exception = InvalidFilterTypeException::class;
163+
$this->fail("Expected exception $exception not thrown");
164+
} catch (InvalidFilterTypeException $exception) {
165+
$this->assertEquals("invalid filter type", $exception->getMessage());
166+
}
167+
168+
// string
169+
$filter = "v0 = bob";
170+
$e->loadFilteredPolicy($filter);
171+
$this->assertEquals([
172+
['bob', 'data2', 'write']
173+
], $e->getPolicy());
174+
175+
// Filter
176+
$filter = new Filter(['v2'], ['read']);
177+
$e->loadFilteredPolicy($filter);
178+
$this->assertEquals([
179+
['alice', 'data1', 'read'],
180+
['data2_admin', 'data2', 'read'],
181+
], $e->getPolicy());
182+
183+
// Closure
184+
$e->loadFilteredPolicy(function ($query) {
185+
$query->where('v1', 'data1');
186+
});
187+
188+
$this->assertEquals([
189+
['alice', 'data1', 'read'],
190+
], $e->getPolicy());
191+
}
146192
}

0 commit comments

Comments
 (0)